{
  "openapi": "3.1.0",
  "info": {
    "title": "Pantech Dynamics public API",
    "version": "1.0.0",
    "description": "The Pantech Dynamics public API lets your scripts, CI pipelines and tools manage everything you run on Pantech: instances, VPC networks, firewalls, public IPs, load balancers, volumes, snapshots, managed databases, managed Kubernetes clusters, SSH keys and webhooks.\n\n**Base URL:** `https://api.pantechdynamics.com/public/v1`\n\n**Authentication.** Every request needs an API key: `Authorization: Bearer PAN_…`. Create one in the console under Organization › API keys. A `read` key can call every GET; a `write` key can also create, change and delete. A key acts as the member who created it, with no more access than they have. `DELETE /me` revokes the key that sends it.\n\n**AI apps.** When a member connects an AI app (an AI assistant or coding tool) to Pantech, the app is given an API key of kind `ai_app`, shown under Organization › AI apps; `GET /me` reports `kind` and `client_name`. Its access is the level the member chose: `read` (Read only), `write` (Manage) or `write` plus `delete` (Manage and delete). An `ai_app` key with `write` but not `delete` can create and change resources but cannot make a destructive call — every DELETE except `DELETE /me`, rebuilding or restoring an instance, and lowering a snapshot schedule's `retention_count` (these operations are marked `x-destructive`); it gets `403 INSUFFICIENT_SCOPE` instead. A standard key's `write` covers destructive calls as it always has. Owners can turn AI app access off for the whole organization: every request made with an `ai_app` key, and every request sent by Pantech's MCP server (it sends the header `Pantech-Client: mcp/<version>`, whatever key it uses), then gets `403 AI_APPS_DISABLED` until it is turned back on. `DELETE /me` keeps working so an app can always be disconnected.\n\n**Asynchronous changes.** Writes return `202 Accepted` with an `operation_id`. Poll `GET /operations/{operation_id}` (or stream `/events`) until `status` is `succeeded` or `failed`. A new instance or database returns an order instead: follow `GET /instance-orders/{order_id}` or `GET /database-orders/{order_id}`.\n\n**Idempotency.** Every POST, PUT and DELETE needs an `Idempotency-Key` header. Retrying with the same key returns the original result instead of repeating the change. Some endpoints do not replay, and say so: `POST /ssh-keys`, `DELETE /ssh-keys/{ssh_key_id}`, `POST /instances/{instance_id}/console`, and the webhook test, delete, secret rotation and redelivery endpoints.\n\n**Errors.** Every error is `application/problem+json` with a stable `code`, a plain-language `detail` that says what went wrong and what to do, and a `request_id` to quote to support. Branch on `code`, never on `detail`. A `422 VALIDATION_FAILED` lists each invalid field in `errors` (`field`, `code`, `message`). Each endpoint below lists the codes it can return. Two more apply everywhere: `404 ROUTE_NOT_FOUND` (no endpoint matches the method and path) and `500 INTERNAL` (something failed on our side; retry with the same `Idempotency-Key`, and contact support with the `request_id` if it persists).\n\n**Failed operations.** An operation that fails has `status: failed` and a `failure` with a stable `code` and a readable `reason`, safe to show to your users. Common codes: `INSTANCE_BUSY` (the resource kept changing; retry when it has settled), `SECURITY_GROUP_ALLOWS_PRIVATE_NETWORK` (see *Add a private database network interface*), `DATABASE_STORAGE_RESIZE_FAILED` and `DATABASE_STORAGE_GROW_FAILED` (nothing changed and nothing extra is billed; retry later).\n\n**Pagination.** Lists return `{ \"data\": [...], \"next_cursor\": ... }`. Pass `next_cursor` as `cursor` until it is null.\n\n**Rate limits.** 300 requests/minute per key, plus shared verified-user and organization budgets (defaults: 1,200/minute per user and 6,000/minute per organization, including console traffic). Changing IPs or keys does not reset those budgets. Authenticated responses carry `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`; successful calls report the key budget. A quota `429` reports the denying budget and `RateLimit-Scope` (`api_key`, `user` or `organization`). Every `429` carries `Retry-After`. Separate edge/IP and failed-auth limits can refuse requests before these quotas.\n\n**Money.** Amounts are integers in minor units (`amount_minor`): kobo for NGN, cents for USD.",
    "contact": {
      "name": "Pantech Dynamics support",
      "url": "https://pantechdynamics.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://api.pantechdynamics.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The API key making the call."
    },
    {
      "name": "Catalogue",
      "description": "What you can buy, and what it costs."
    },
    {
      "name": "Instances",
      "description": "Virtual machines (VPS): create, power, change, delete."
    },
    {
      "name": "Instance orders",
      "description": "How a new instance is paid for and provisioned."
    },
    {
      "name": "Networks",
      "description": "VPCs, subnets and their firewall rules."
    },
    {
      "name": "Public IPs",
      "description": "Public addresses for VPC instances, and port forwarding."
    },
    {
      "name": "Load balancers",
      "description": "Spread traffic on one public port across several instances in a private network."
    },
    {
      "name": "Kubernetes",
      "description": "Managed Kubernetes clusters whose nodes are VMs in your account."
    },
    {
      "name": "Security groups",
      "description": "Reusable firewalls for standard instances."
    },
    {
      "name": "Volumes",
      "description": "Data disks."
    },
    {
      "name": "Databases",
      "description": "Managed PostgreSQL, MySQL and MariaDB databases, reachable only from your own network."
    },
    {
      "name": "Snapshots",
      "description": "Point-in-time copies of root disks and volumes, and automatic schedules."
    },
    {
      "name": "SSH keys",
      "description": "Keys installed on new instances."
    },
    {
      "name": "Webhooks",
      "description": "Events sent to your own URL when something changes: resources finishing or failing a change, invoices, payments and credit."
    },
    {
      "name": "Operations",
      "description": "Follow asynchronous changes."
    },
    {
      "name": "Usage",
      "description": "What has been used, and what it cost."
    },
    {
      "name": "Billing",
      "description": "Your credit, and whether it covers your next invoice."
    }
  ],
  "paths": {
    "/public/v1/billing/credit": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get credit",
        "description": "Your organization's credit, and how it compares with your next invoice.\n\n`estimated_next_invoice_minor` is usage so far this billing period plus the recent daily rate for the days left, plus 7.5% VAT on that (VAT applies only to the monthly invoice, never to credit purchases). It is an estimate: the invoice issued at `next_invoice_at` is the real figure. `standing` is `covered` when credit and prepaid instance payments cover the estimate, `low` when they don't, and `empty` when no credit is left. Anything credit doesn't cover is charged to your default payment method.\n\nCheck this before creating resources from automation, or poll it to top up in time. Owners and admins are also emailed once when credit becomes `low` and once when it becomes `empty`. To add credit, see *Buy credit*.\n\n**Scope:** `read`.",
        "operationId": "getCredit",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 86,
        "responses": {
          "200": {
            "description": "Credit.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditOutlook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/billing/credit/purchases": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Buy credit",
        "description": "Creates a payment link to add credit to your organization. Send `checkout_url` to whoever pays: it opens the payment provider's own secure page, so no card details ever pass through your systems or ours. Organizations pay in NGN or USD. The currency follows your organization's country and can't be chosen.\n\nNothing is charged until someone pays the link. The credit is added once the provider confirms the payment, usually within a minute: follow the purchase with `GET /public/v1/billing/credit/purchases/{purchase_id}` until `status` is `settled`, and the owners and admins get a receipt by email. A link that isn't paid expires at `checkout_expires_at`; create a new purchase after that.\n\nOne purchase is between NGN 500 and NGN 500,000 (`50000` to `50000000` kobo), or between USD 5 and USD 2,000 (`500` to `200000` cents).\n\nSend an `Idempotency-Key`: a retry with the same key returns the same purchase and the same link. The member who created the key must be an owner or admin with a verified email.\n\n**Scope:** `write`.",
        "operationId": "createCreditPurchase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 87,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCreditPurchaseRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The purchase, with its `checkout_url`.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditPurchase"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE`: this API key has only the `read` scope. Use a key with `write` access.\n`FORBIDDEN`: only an owner or admin may buy credit. Use a key created by an owner or admin.\n`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server. An owner can turn it on in the console under Organization › AI apps.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`EMAIL_VERIFICATION_REQUIRED`: the member who created this key has not verified their email, where the receipt is sent. Verify it in the console, then retry.\n`CREDIT_PURCHASE_UNAVAILABLE`: credit can't be bought for this organization yet. Finish billing setup in the console, or contact support.\n`IDEMPOTENCY_CONFLICT`: this `Idempotency-Key` was already used for a different amount. Use a new key for a different purchase.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`amount_minor` `REQUIRED`: send a positive amount in minor units.\n`amount_minor` `AMOUNT_OUT_OF_RANGE`: the amount is outside the per-purchase limits above for your currency. Choose an amount within them.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/billing/credit/purchases/{purchase_id}": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get a credit purchase",
        "description": "One credit purchase: whether it has been paid. `checkout_url` is shown only while the purchase can still be paid. Poll this after *Buy credit* until `status` is `settled` (credit added), or `failed` or `expired` (nothing charged; create a new purchase).\n\n**Scope:** `read`.",
        "operationId": "getCreditPurchase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 88,
        "parameters": [
          {
            "name": "purchase_id",
            "in": "path",
            "required": true,
            "description": "The purchase's id, e.g. `cpr_...`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The purchase.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditPurchase"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no credit purchase with this id in your organization. Check the id (`cpr_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/billing/receipts": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "List receipts",
        "description": "Every receipt issued to your organization, newest first. A receipt is issued, numbered `PTD-RCT-<year>-<number>`, whenever money moves: a card payment, a credit top-up, an invoice paid by card or from credit, a debit from your credit (for example a new instance's first charges), and a refund. A payment's receipt usually appears within a minute of it settling.\n\n**Scope:** `read`.",
        "operationId": "listReceipts",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 107,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of receipts.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceiptList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_CURSOR`: the cursor did not come from this list. Start again without one.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/billing/receipts/{receipt_id}": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get a receipt",
        "description": "One receipt: what it was for, the amount, who issued it and the details printed on it. Download it as a PDF with `GET /public/v1/billing/receipts/{receipt_id}/pdf`.\n\n**Scope:** `read`.",
        "operationId": "getReceipt",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 108,
        "parameters": [
          {
            "name": "receipt_id",
            "in": "path",
            "required": true,
            "description": "The receipt's id, e.g. `rcp_...`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The receipt.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Receipt"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RECEIPT_NOT_FOUND`: no receipt with this id in your organization. List your receipts to find it.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/billing/receipts/{receipt_id}/pdf": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Download a receipt",
        "description": "The receipt as a PDF, the same document that was emailed. The file name is the receipt number, e.g. `PTD-RCT-2026-000123.pdf`.\n\n**Scope:** `read`.",
        "operationId": "getReceiptPdf",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 109,
        "parameters": [
          {
            "name": "receipt_id",
            "in": "path",
            "required": true,
            "description": "The receipt's id, e.g. `rcp_...`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The PDF.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Content-Disposition": {
                "description": "`attachment; filename=\"PTD-RCT-2026-000123.pdf\"`.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RECEIPT_NOT_FOUND`: no receipt with this id in your organization. List your receipts to find it.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/database-engines": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "List database engines",
        "description": "The engines and version lines you can create a managed database with: PostgreSQL, MySQL and MariaDB, long-term-support lines only. A version appears only while it is offered for new databases, and `zones` lists the zones it can be created in. An engine with no offered version has an empty `versions` list.\n\nUse `engine` and a `version` from here, and a zone from that version's `zones`, in *Create a database*.\n\n**Scope:** `read`.",
        "operationId": "listDatabaseEngines",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 89,
        "responses": {
          "200": {
            "description": "The engines.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabaseEngineList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/database-orders": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "List database orders",
        "description": "Your database orders, newest first, one per *Create a database* call. An order shows whether the initial payment was taken and whether provisioning started. Never includes a password.\n\n**Scope:** `read`.",
        "operationId": "listDatabaseOrders",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 99,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of orders.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabaseOrderList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/database-orders/{order_id}": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "Get a database order",
        "description": "Payment and provisioning progress for one new database. Poll it after *Create a database* until `status` is `provisioned` (then read the database at `GET /public/v1/databases/{database_id}`), or `payment_failed` or `failed` (final: any payment taken is returned to your credit, and `failure_code` says why). Once `operation_id` is set you can also follow that operation. Never includes a password.\n\n**Scope:** `read`.",
        "operationId": "getDatabaseOrder",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 100,
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabaseOrder"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_ORDER_NOT_FOUND`: no database order with this id in your organization. Check the id; an order of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not an order id (`ord_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/databases": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "List databases",
        "description": "Your managed databases, oldest first, with each one's hostname, state and access rules. Filter by name with `q`, or by state. Never includes a password.\n\nDatabases whose create failed are hidden by default; list them with `observed_state=failed` (their failure is in `failure_code`), and delete them to clean up.\n\n**Scope:** `read`.",
        "operationId": "listDatabases",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 90,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/InstanceDesiredState"
          },
          {
            "$ref": "#/components/parameters/InstanceObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of databases.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabaseList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Create a database",
        "description": "Creates a single-node PostgreSQL, MySQL or MariaDB database on its own server, sized by a plan (vCPU and memory), with its own data disk, and never on a public address. You connect to it by its `hostname` from your own network.\n\n**Placement.** Pick a zone where your engine version is offered (`GET /public/v1/database-engines`). In a VPC zone (`af-abj-2`) `subnet_id` is required, and unless you send `access_rules` the database starts allowing the subnet's VPC CIDR. In a standard zone (`af-abj-1`) leave out `subnet_id`; the database starts allowing nobody until you add access rules or attach security groups, and your instances reach it after *Add a private database network interface*.\n\n**Paid first, like an instance.** The request records an order and returns `202 Accepted` with it (`order_id`, also the `Location` header). The initial payment is then taken from credit, or else from the organization's default card, and the database is provisioned. It costs exactly what an instance of the same plan with no public address costs, with `storage_gb` as its disk (`amount_minor` is the upfront payment). Follow `GET /public/v1/database-orders/{order_id}` until `status` is `provisioned`, then read the database; `payment_failed` and `failed` are final, and any payment taken is returned to your credit.\n\n**Admin login.** Send `admin_username` to name the database's admin login, or leave it out for `dbadmin`. It is not a superuser: on PostgreSQL and MySQL it can create further users and databases; on MariaDB it is the only login.\n\n**Admin password.** Send `password` to choose it (16 to 128 printable ASCII characters, with no spaces, quotes or backslashes); it is never returned. Leave it out and a 32-character password is generated and **returned once, in this response** (`password`). Until provisioning starts the password is held only encrypted, then erased: it cannot be read again (use *Reset the password* for a new one). Every response is `Cache-Control: no-store`. Infrastructure-as-code tools should keep the password out of state (for Terraform, a write-only attribute).\n\n**Storage.** Leave out `storage_gb` for the plan's `disk_gb`, or ask for more: at most 2000 GB, and above the plan's size a multiple of 10 GB. Read each zone's allowed sizes and price from `storage` in `GET /public/v1/database-engines` rather than hard-coding them. It can be grown later with *Grow a database's storage*, never shrunk.\n\n**Idempotency.** Send an `Idempotency-Key`. A retry with the same key returns the original order with `password_returned: false` and a null `password`: a generated password is shown only on the first response.\n\n**Scope:** `write`.",
        "operationId": "createDatabase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 91,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDatabaseRequest"
              },
              "examples": {
                "generated_password": {
                  "summary": "PostgreSQL in a VPC subnet, password generated",
                  "value": {
                    "name": "orders-db",
                    "engine": "postgresql",
                    "version": "18",
                    "plan_slug": "starter",
                    "zone_id": "af-abj-2",
                    "subnet_id": "snet_06gk3x9tq7m2v8r4y1c5d0zp8w"
                  }
                },
                "chosen_password": {
                  "summary": "MySQL in a standard zone, with your own password, admin login and a bigger disk",
                  "value": {
                    "name": "orders-db",
                    "engine": "mysql",
                    "version": "8.4",
                    "plan_slug": "starter",
                    "zone_id": "af-abj-1",
                    "access_rules": [
                      "10.250.3.17/32"
                    ],
                    "admin_username": "app_admin",
                    "password": "c0rrect-H0rse-battery-St4ple",
                    "storage_gb": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Ordered. Follow `order_id` (also the `Location` header) until provisioning starts.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Always `no-store`: this response may carry a password.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabaseOrderAccepted"
                },
                "examples": {
                  "generated_password": {
                    "summary": "Password generated: returned once, here",
                    "value": {
                      "order_id": "ord_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "database_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "awaiting_payment",
                      "operation_id": null,
                      "failure_code": null,
                      "amount_minor": 1504000,
                      "currency": "NGN",
                      "password_returned": true,
                      "password": "q8Vn3TzK1mXw7RbLc4Hs9JdP2fYa6GeU",
                      "admin_username": "dbadmin"
                    }
                  },
                  "chosen_password": {
                    "summary": "You chose the password, or this is a retry: no password returned",
                    "value": {
                      "order_id": "ord_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "database_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "awaiting_payment",
                      "operation_id": null,
                      "failure_code": null,
                      "amount_minor": 1504000,
                      "currency": "NGN",
                      "password_returned": false,
                      "password": null,
                      "admin_username": "app_admin"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "description": "`INSUFFICIENT_CREDIT`: the initial payment is more than your available credit and the organization has no default card; `detail` gives both amounts. Buy credit (`POST /public/v1/billing/credit/purchases`) or add a card in the console, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`ACCOUNT_NOT_ACTIVE`: the organization's billing account is not active yet. Finish billing setup in the console (verify the organization and add a payment method), then retry.\n`DATABASE_NAME_TAKEN`: you already have a database with this name. Choose a different name.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `INVALID_DATABASE_NAME`: the name is empty or longer than 255 characters.\n`engine` `INVALID_DATABASE_ENGINE`: use `postgresql`, `mysql` or `mariadb`.\n`version` `INVALID_DATABASE_VERSION`: the version line is not offered for new databases. Pick one from `GET /public/v1/database-engines`.\n`zone_id` `INVALID_DATABASE_ZONE`: the zone is missing or not one your organization can use. Pick one from `GET /public/v1/regions`.\n`zone_id` `DATABASE_VERSION_NOT_AVAILABLE_IN_ZONE`: this version is not offered in this zone yet. Pick a zone from the version's `zones`.\n`plan_slug` `PLAN_NOT_FOUND`: no active plan has this slug. Pick one from `GET /public/v1/plans`.\n`subnet_id` `DATABASE_SUBNET_REQUIRED`: a VPC zone needs a subnet. Send the `subnet_id` of one of your subnets in that zone.\n`subnet_id` `DATABASE_SUBNET_NOT_ALLOWED`: a standard zone takes no subnet. Leave out `subnet_id`.\n`subnet_id` `DATABASE_SUBNET_NOT_FOUND`: no subnet with this id in your organization. Check the id.\n`subnet_id` `DATABASE_SUBNET_WRONG_ZONE`: the subnet is in another zone. Use a subnet in `zone_id`.\n`subnet_id` `DATABASE_SUBNET_NOT_USABLE`: the subnet is being deleted or has failed. Use another subnet.\n`access_rules` `INVALID_ACCESS_RULE`: each rule must be an IPv4 CIDR with a prefix of /8 or longer, such as `10.0.1.0/24` or `10.250.3.17/32`; `0.0.0.0/0` is refused.\n`access_rules` `TOO_MANY_ACCESS_RULES`: at most 50 rules. Merge neighbouring ranges, or attach a security group.\n`access_rules` `DUPLICATE_ACCESS_RULE`: the same range appears twice (after masking host bits). Remove the repeat.\n`admin_username` `INVALID_DATABASE_ADMIN_USERNAME`: use 3 to 32 lowercase letters, digits or underscores, starting with a letter, and not a reserved name (`root`, `postgres`, `public`, `none`, `all`, `user`, `sys`, `system`, `replication`, `current_user`, `current_role`, `session_user`, or a name starting with `pg_`, `mysql`, `mariadb` or `pantech`).\n`password` `INVALID_DATABASE_PASSWORD`: use 16 to 128 printable ASCII characters with no spaces, single or double quotes, or backslashes; or leave it out to have one generated.\n`storage_gb` `INVALID_DATABASE_STORAGE`: use at least the plan's `disk_gb`, at most 2000, and above the plan's size a multiple of 10. Leave it out for the plan's size.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`DATABASES_UNAVAILABLE`: managed databases are not available on this platform yet. Try again later, or contact support.\n`DATABASE_STORAGE_UNAVAILABLE`: database storage is not offered in this zone yet. Choose another zone, or try again later.\n`DATABASE_HOSTNAME_UNAVAILABLE`: a hostname could not be reserved for the database. Retry with a new `Idempotency-Key`.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "Get a database",
        "description": "One database: its connection `hostname` and `port`, `admin_username`, state, data disk size, access rules, attached security groups and the allow-list it applies (`effective_access_rules`). Never includes a password.\n\nA change you requested is in effect once `observed_generation` equals `generation`. Connect as `admin_username` to `hostname`:`port` from an address its allow-list includes.\n\n**Scope:** `read`.",
        "operationId": "getDatabase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 92,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The database.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Database"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Databases"
        ],
        "summary": "Delete a database",
        "description": "Deletes the database. Its hostname is removed first, then its server is retired. Its data disk and a safety snapshot of it are kept for a short retention period (12 and 24 hours) and then destroyed; nothing is billed for them during retention. Snapshots you took yourself are kept and stay billed until you delete them.\n\nOnce the delete succeeds, the part of the database's upfront payment that no invoice has drawn yet goes back to your organization's credit balance, never to the card. Usage up to the delete is invoiced as usual. A delete that fails returns nothing.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteDatabase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 93,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused a value, for example a malformed CIDR or a name longer than 255 characters. Check the request against this page.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/access-rules": {
      "put": {
        "tags": [
          "Databases"
        ],
        "summary": "Replace access rules",
        "description": "Replaces the database's whole allow-list. Each rule allows TCP to the engine's port (5432 for PostgreSQL, 3306 for MySQL and MariaDB) from one IPv4 CIDR. Send `[]` to remove every rule. To let one instance in, allow its address as a `/32`: in a standard zone, use the instance's `private_network_ip` after *Add a private database network interface*.\n\nLimits: an IPv4 CIDR with a prefix of `/8` or longer (host bits are masked, so `10.0.1.7/24` becomes `10.0.1.0/24`); never `0.0.0.0/0`; at most 50 rules; no range twice. These rules plus the ranges added by attached security groups may total at most 1024.\n\nRemoving a rule also ends connections already open from that range. Returns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The new list is in effect once the database's `observed_generation` equals its `generation`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "replaceDatabaseAccessRules",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 96,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceDatabaseAccessRulesRequest"
              },
              "examples": {
                "two_ranges": {
                  "summary": "Allow a VPC subnet and one instance's private interface",
                  "value": {
                    "rules": [
                      {
                        "cidr": "10.0.1.0/24"
                      },
                      {
                        "cidr": "10.250.3.17/32"
                      }
                    ]
                  }
                },
                "none": {
                  "summary": "Allow nobody",
                  "value": {
                    "rules": []
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`rules` `REQUIRED`: send the complete list; `[]` removes every rule.\n`rules` `INVALID_ACCESS_RULE`: each `cidr` must be an IPv4 CIDR with a prefix of /8 or longer, such as `10.0.1.0/24`; `0.0.0.0/0` is refused.\n`rules` `TOO_MANY_ACCESS_RULES`: at most 50 rules. Merge neighbouring ranges, or attach a security group instead.\n`rules` `DUPLICATE_ACCESS_RULE`: the same range appears twice (after masking host bits). Remove the repeat.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`DATABASE_ACCESS_RANGE_LIMIT_EXCEEDED`: the database's own access rules plus the address ranges its security groups add would exceed 1024. Remove access rules, detach a security group, or narrow the groups' rules, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/security-groups": {
      "put": {
        "tags": [
          "Databases"
        ],
        "summary": "Attach security groups",
        "description": "Replaces the set of your security groups attached to the database; `[]` detaches every group. At most 5, each one of your own security groups in the database's zone that is not being deleted or failed. Another organization's group is reported as not found.\n\nA group is only a **source of address ranges** for the database: each of its **ingress** rules whose protocol is `tcp` or `all`, whose ports include the engine's port (5432 or 3306; a range such as `3000-4000`, or all ports, counts) and whose CIDR is IPv4 with a prefix of `/8` or longer adds its CIDR to the database's allow-list, beside its own access rules. Every other rule (other ports, egress, `udp`, `icmp`, `0.0.0.0/0` and anything wider than `/8`, IPv6) is ignored for the database and listed in `ignored_security_group_rules` with the reason. The group itself is never applied to the database server, and SSH to it is never opened. The database's access rules plus the ranges its groups add may total at most 1024.\n\nWhen an attached group's rules change, the database is updated automatically. A group cannot be deleted while a database uses it (`409 SECURITY_GROUP_ATTACHED_TO_DATABASE`); detach it here first.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "setDatabaseSecurityGroups",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 101,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetDatabaseSecurityGroupsRequest"
              },
              "examples": {
                "attach": {
                  "summary": "Attach one security group",
                  "value": {
                    "security_group_ids": [
                      "sg_06gk3x9tq7m2v8r4y1c5d0zp8w"
                    ]
                  }
                },
                "detach_all": {
                  "summary": "Detach every group",
                  "value": {
                    "security_group_ids": []
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`security_group_ids` `REQUIRED`: send the complete set; `[]` detaches every group.\n`security_group_ids` `INVALID_DATABASE_SECURITY_GROUPS`: more than 5 ids, or an id repeated. Send at most 5 distinct ids.\n`security_group_ids` `DATABASE_SECURITY_GROUP_NOT_FOUND`: an id is not one of your security groups. Check the ids with `GET /public/v1/security-groups`.\n`security_group_ids` `DATABASE_SECURITY_GROUP_NOT_USABLE`: a group is being deleted or has failed. Remove it from the list.\n`security_group_ids` `DATABASE_SECURITY_GROUP_WRONG_ZONE`: a group is in another zone than the database. Use groups in the database's zone.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`DATABASE_ACCESS_RANGE_LIMIT_EXCEEDED`: the database's own access rules plus the address ranges its security groups add would exceed 1024. Remove access rules, detach a security group, or narrow the groups' rules, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/password": {
      "put": {
        "tags": [
          "Databases"
        ],
        "summary": "Set the password",
        "description": "Sets the admin login's password to one you choose: 16 to 128 printable ASCII characters, with no spaces, single or double quotes, or backslashes. It is applied inside the database and never stored or returned. The database must be running. Existing connections stay open; new ones need the new password once the operation succeeds.\n\nUse this from infrastructure-as-code to rotate a password you manage; use *Reset the password* to have one generated instead. The response is `Cache-Control: no-store`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "changeDatabasePassword",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 97,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangeDatabasePasswordRequest"
              },
              "examples": {
                "rotate": {
                  "summary": "Set a password you manage",
                  "value": {
                    "password": "c0rrect-H0rse-battery-St4ple"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Always `no-store`: this response may carry a password.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`DATABASE_NOT_RUNNING`: the database must be running for this change. Start it (`POST /public/v1/databases/{database_id}/start`), wait for the operation to succeed, then retry.\n`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`password` `REQUIRED`: send the new password.\n`password` `INVALID_DATABASE_PASSWORD`: use 16 to 128 printable ASCII characters with no spaces, single or double quotes, or backslashes.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/reset-password": {
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Reset the password",
        "description": "Replaces the admin login's password with a generated one (32 letters and digits), returned once in this response (`password`) with `Cache-Control: no-store`, and never stored. The database must be running. Use this when the password is lost: support cannot recover it.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The new password works once the operation succeeds.\n\n**Idempotency.** Send an `Idempotency-Key`. A retry with the same key returns the original operation with `password_returned: false` and a null `password`: if the first response was lost, reset again with a new key.\n\n**Scope:** `write`.",
        "operationId": "resetDatabasePassword",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 98,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Always `no-store`: this response may carry a password.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatabasePasswordAccepted"
                },
                "examples": {
                  "first": {
                    "summary": "First response: the new password, once",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting",
                      "password_returned": true,
                      "password": "q8Vn3TzK1mXw7RbLc4Hs9JdP2fYa6GeU"
                    }
                  },
                  "retry": {
                    "summary": "Retry with the same key: no password",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting",
                      "password_returned": false,
                      "password": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`DATABASE_NOT_RUNNING`: the database must be running for this change. Start it (`POST /public/v1/databases/{database_id}/start`), wait for the operation to succeed, then retry.\n`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/start": {
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Start a database",
        "description": "Starts a stopped database. Its hostname, data and access rules are unchanged. A running database is billed for its plan again.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "startDatabase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 94,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/stop": {
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Stop a database",
        "description": "Shuts the database down cleanly. A stopped database keeps its data, hostname and access rules, refuses connections, and is billed for its storage only. Start it again with *Start a database*.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "stopDatabase",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 95,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/resize-storage": {
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Grow a database's storage",
        "description": "Grows the database's data disk to `storage_gb`. vCPU and memory stay the plan's. The disk only grows: `storage_gb` must be larger than the current `data_volume_size_gb`, at most 2000 GB and a multiple of 10 GB (read the zone's limits from `storage` in `GET /public/v1/database-engines` rather than hard-coding them). The database must be running; the filesystem grows online, without a restart. One resize at a time.\n\nNo upfront charge, as for an instance resize: storage is billed hourly, at the new size only once the resize has completed. While it runs, `pending_data_volume_size_gb` shows the size in flight; `data_volume_size_gb` changes when it succeeds. A failed resize leaves the size and the bill unchanged.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "resizeDatabaseStorage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 102,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResizeDatabaseStorageRequest"
              },
              "examples": {
                "grow": {
                  "summary": "Grow the data disk to 200 GB",
                  "value": {
                    "storage_gb": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`DATABASE_NOT_RUNNING`: the database must be running for this change. Start it (`POST /public/v1/databases/{database_id}/start`), wait for the operation to succeed, then retry.\n`DATABASE_STORAGE_RESIZE_IN_PROGRESS`: a storage resize of this database is still running. Wait for its operation to finish, then retry.\n`INVALID_RESOURCE_STATE`: the database is being deleted or has been deleted. Nothing more can be changed on it.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`storage_gb` `REQUIRED`: send the new size in GB.\n`storage_gb` `INVALID_DATABASE_STORAGE`: the size must be larger than the current `data_volume_size_gb`, at most 2000, and a multiple of 10.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`DATABASE_STORAGE_UNAVAILABLE`: database storage is not offered in this database's zone right now. Try again later.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/snapshots": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "List a database's snapshots",
        "description": "Snapshots of the database's data disk, oldest first. Each is also listed in `GET /public/v1/snapshots`, with `database_id` set.\n\n**Scope:** `read`.",
        "operationId": "listDatabaseSnapshots",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 103,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of snapshots.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotList"
                },
                "examples": {
                  "one": {
                    "summary": "One crash-consistent snapshot",
                    "value": {
                      "data": [
                        {
                          "id": "snap_06gk3x9tq7m2v8r4y1c5d0zp8w",
                          "name": "pre-upgrade",
                          "instance_id": null,
                          "source_instance_name": null,
                          "volume_id": null,
                          "volume_name": null,
                          "database_id": "db_06gk3x9tq7m2v8r4y1c5d0zp8w",
                          "region": "af-abj",
                          "trigger": "manual",
                          "size_bytes": 1610612736,
                          "desired_state": "present",
                          "observed_state": "active",
                          "completed_at": "2026-10-03T09:31:12Z",
                          "created_at": "2026-10-03T09:30:00Z",
                          "updated_at": "2026-10-03T09:31:12Z"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Snapshot a database",
        "description": "Takes a snapshot of the database's data disk. The engine keeps running, so the snapshot is **crash-consistent only**: what the disk held at that instant, as after a power cut, which the engine recovers from on start. It is not an engine-level backup; stop the database first for a quiesced copy. The database must be running or stopped.\n\nBilled like every snapshot: the storage rate on its physical size, for every started hour until it is deleted. A snapshot outlives its database and stays billed until you delete it. Restoring a database from a snapshot is not available yet.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The new snapshot's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createDatabaseSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 104,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSnapshotRequest"
              },
              "examples": {
                "named": {
                  "summary": "Name the snapshot",
                  "value": {
                    "name": "pre-upgrade"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted; the new snapshot's id is resource_id",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "snap_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`DATABASE_SNAPSHOT_NOT_READY`: the database is not running or stopped (it is starting, stopping, being created or deleted). Wait until it is running or stopped, then retry.\n`DATABASE_SNAPSHOT_NAME_TAKEN`: this database already has a snapshot with that name. Choose a different name.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `INVALID_DATABASE_SNAPSHOT_NAME`: the name is empty or longer than 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`DATABASES_UNAVAILABLE`: managed databases are not available on this platform yet. Try again later, or contact support.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/databases/{database_id}/snapshots/{snapshot_id}": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "Get a database's snapshot",
        "description": "One snapshot of the database's data disk.\n\n**Scope:** `read`.",
        "operationId": "getDatabaseSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 105,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "The snapshot's id, e.g. `snap_...`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The snapshot.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.\n`DATABASE_SNAPSHOT_NOT_FOUND`: this database has no snapshot with this id (a snapshot of an instance or volume is reported the same way). Check the id, or use `GET /public/v1/snapshots/{snapshot_id}`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Databases"
        ],
        "summary": "Delete a database's snapshot",
        "description": "Deletes one snapshot of the database's data disk. It is billed until the deletion completes.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteDatabaseSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 106,
        "parameters": [
          {
            "name": "database_id",
            "in": "path",
            "required": true,
            "description": "The database's id, e.g. `db_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "The snapshot's id, e.g. `snap_...`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DATABASE_NOT_FOUND`: no database with this id in your organization. Check the id: a database of another organization is reported the same way.\n`RESOURCE_NOT_FOUND`: the id is not a database id (`db_…`). Check the path.\n`DATABASE_SNAPSHOT_NOT_FOUND`: this database has no snapshot with this id. Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the snapshot cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/disk-offerings": {
      "get": {
        "tags": [
          "Catalogue"
        ],
        "summary": "List disk offerings",
        "description": "Volume types and their hourly prices. Use a `slug` as `disk_offering_slug` in *Create a volume*; for an offering with `custom_size: true`, also send `size_gb`.\n\n**Scope:** `read`.",
        "operationId": "listDiskOfferings",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 5,
        "responses": {
          "200": {
            "description": "Disk offerings.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiskOfferingList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/disk-offerings/{slug}/quote": {
      "get": {
        "tags": [
          "Catalogue"
        ],
        "summary": "Price a volume",
        "description": "The monthly price of one volume of this offering. `size_gb` is required for a custom-size offering and ignored otherwise. Use it to show a price before *Create a volume*.\n\n**Scope:** `read`.",
        "operationId": "quoteDiskOffering",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 6,
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The disk offering's slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "size_gb",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The price.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "disk_offering_slug",
                    "size_gb",
                    "currency",
                    "hourly_price_minor",
                    "monthly_price_minor"
                  ],
                  "properties": {
                    "disk_offering_slug": {
                      "type": "string"
                    },
                    "size_gb": {
                      "type": "integer"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "hourly_price_minor": {
                      "type": "integer",
                      "format": "int64"
                    },
                    "monthly_price_minor": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no active disk offering has this slug. Pick one from `GET /public/v1/disk-offerings`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`size_gb` `INVALID_SIZE`: send a whole number of GB, at least 1.\n`size_gb` `SIZE_REQUIRED`: this offering is custom-size, so `size_gb` is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/firewall-rules/{rule_id}": {
      "delete": {
        "tags": [
          "Networks"
        ],
        "summary": "Delete a firewall rule",
        "description": "Deletes one subnet firewall rule. Traffic it allowed is dropped once the operation succeeds, unless another rule allows it.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteFirewallRule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 45,
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "description": "The rule's id (`aclr_...` for a firewall rule, `pfr_...` for a port forwarding rule).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no firewall rule with this id in your organization, or the id is not a firewall rule id (`aclr_…`). Check the id.\n`NOT_FOUND`: firewall rules are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the firewall rule cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/images": {
      "get": {
        "tags": [
          "Catalogue"
        ],
        "summary": "List images",
        "description": "Operating systems you can install on an instance, and the zones each runs in. Use a `slug` as `image_slug` in *Create an instance* or *Rebuild an instance*.\n\nEncrypted images (`encrypted: true`) appear only for organizations they are enabled for; elsewhere their slug is refused as `IMAGE_NOT_FOUND`.\n\n**Scope:** `read`.",
        "operationId": "listImages",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 4,
        "responses": {
          "200": {
            "description": "Images.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/instance-orders": {
      "get": {
        "tags": [
          "Instance orders"
        ],
        "summary": "List instance orders",
        "description": "Your instance orders, newest first, one per *Create an instance* call. An order shows whether the initial payment was taken and whether provisioning started.\n\n**Scope:** `read`.",
        "operationId": "listInstanceOrders",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 31,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of orders.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceOrderList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/instance-orders/{order_id}": {
      "get": {
        "tags": [
          "Instance orders"
        ],
        "summary": "Get an instance order",
        "description": "Payment and provisioning progress for one new instance. Poll it after *Create an instance* until `status` is `provisioned` (then read the instance), or `payment_failed` or `failed` (final: any payment taken is returned to your credit, and `failure_code` says why).\n\n**Scope:** `read`.",
        "operationId": "getInstanceOrder",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 32,
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceOrder"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance order with this id in your organization, or the id is not an order id (`ord_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/instances": {
      "get": {
        "tags": [
          "Instances"
        ],
        "summary": "List instances",
        "description": "Your instances, newest first, with addresses and state. Filter by name with `q`, or by state.\n\n**Scope:** `read`.",
        "operationId": "listInstances",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 8,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/InstanceDesiredState"
          },
          {
            "$ref": "#/components/parameters/InstanceObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of instances.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Create an instance",
        "description": "Orders a new instance (VPS). Choose a plan (`GET /public/v1/plans`), an image (`GET /public/v1/images`) and an SSH key (`GET /public/v1/ssh-keys`), which is required: images have no password login.\n\n**Placement.** Leave out `subnet_id` for a standard instance with its own public IPv4, protected by a security group (your organization's default group unless you send `security_group_id`). Send `subnet_id` (and optionally its `network_id`) to place it in a VPC subnet, with a private address only; reach it through a public IP.\n\n**Paid first.** Returns `202 Accepted` with an order (`order_id`, also the `Location` header). The initial payment is taken from credit, or else from the organization's default card, and then the instance is provisioned. Follow `GET /public/v1/instance-orders/{order_id}` until `status` is `provisioned`, then read the instance; `payment_failed` and `failed` are final, and any payment taken is returned to your credit.\n\n**Idempotency.** Send an `Idempotency-Key`. A retry with the same key returns the original order instead of ordering a second instance.\n\n**Scope:** `write`.",
        "operationId": "createInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 9,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInstanceRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Ordered.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderAccepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "description": "`INSUFFICIENT_CREDIT`: the initial payment is more than your available credit and the organization has no default card; `detail` gives both amounts. Buy credit (`POST /public/v1/billing/credit/purchases`) or add a card in the console, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: `ssh_key_id` is not one of your SSH keys. Check it with `GET /public/v1/ssh-keys`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INSTANCE_NAME_TAKEN`: you already have an instance with this name. Choose a different name.\n`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`ACCOUNT_NOT_ACTIVE`: the organization's billing account is not active yet. Finish billing setup in the console (verify the organization and add a payment method), then retry.\n`PROVIDER_ACCOUNT_NOT_READY`: your organization's cloud account is still being set up, which takes a few minutes after sign-up. Retry shortly.\n`SECURITY_GROUPS_NOT_SUPPORTED_IN_ZONE`: a VPC instance uses its subnet's firewall rules, not a security group. Leave out `security_group_id`.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`ssh_key_id` `REQUIRED`: no SSH key was sent. Send the id of one of your SSH keys (`GET /public/v1/ssh-keys`): images have no password login.\n`plan_slug` `PLAN_NOT_FOUND`: no active plan has this slug. Pick one from `GET /public/v1/plans`.\n`image_slug` `IMAGE_NOT_FOUND`: no active image has this slug. Pick one from `GET /public/v1/images`.\n`image_slug` `IMAGE_NOT_AVAILABLE_IN_ZONE`: the image does not run in the zone this instance goes to. Pick an image whose `zones` include it.\n`encrypted` `ENCRYPTION_NOT_SUPPORTED`: `encrypted` is `true` but this image has no encrypted version available to your organization. Choose an image that offers one, or send `false`.\n`encrypted` `ENCRYPTION_CONFLICT`: `encrypted` is `false` but `image_slug` is an encrypted image. Send `true`, or choose the plain image.\n`security_group_id` `SECURITY_GROUP_NOT_FOUND`: not one of your security groups. Check it with `GET /public/v1/security-groups`.\n`subnet_id` `SUBNET_REQUIRED`: `network_id` was sent without a subnet. Send the subnet too.\n`subnet_id` `SUBNET_NOT_IN_NETWORK`: the subnet is not in `network_id`. Send a subnet of that VPC, or leave out `network_id`.\n`subnet_id` `SUBNET_NOT_FOUND`: no subnet with this id in your organization.\n`subnet_id` `SUBNET_NOT_USABLE`: the subnet is being deleted or has failed. Use another subnet.\n`region` `REGION_NOT_AVAILABLE`: this region cannot take this instance. Pick one from `GET /public/v1/regions`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: the platform refused a value, for example a malformed CIDR or a name longer than 255 characters. Check the request against this page.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}": {
      "get": {
        "tags": [
          "Instances"
        ],
        "summary": "Get an instance",
        "description": "One instance: its plan, image, addresses (including `private_network_ip` once a private database network interface is attached), and current state. A change is complete when `observed_state` matches `desired_state`.\n\n**Scope:** `read`.",
        "operationId": "getInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 10,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The instance.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Instance"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Instances"
        ],
        "summary": "Delete an instance",
        "description": "Deletes the instance. It is stopped, a safety snapshot of its root disk is kept for 24 hours, and then it is removed. Attached volumes are detached, not deleted. Release its public IP and delete port forwarding rules that point at it first.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 23,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INSTANCE_HAS_PUBLIC_IP`: a VPC public IP still maps to this instance. Detach it (`POST /public/v1/public-ips/{public_ip_id}/detach`) to keep the address, or release it (`DELETE /public/v1/public-ips/{public_ip_id}`), then retry.\n`INSTANCE_HAS_PORT_FORWARDS`: port forwarding rules still point at this instance. Delete them, then retry.\n`INSTANCE_BEHIND_LOAD_BALANCER`: the instance is still a load balancer target. Remove it from its load balancers (`PATCH /public/v1/load-balancers/{load_balancer_id}`), then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the instance has already been deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/console": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Open the browser console",
        "description": "Returns a short-lived URL to the instance's browser console. **The console gives a logged-in shell; treat the URL as a password** and never log or share it. The instance must be running.\n\n**Idempotency:** each request opens a new console URL; a retry is not replayed. Opening one changes nothing else, so retrying is safe.\n\n**Scope:** `write`.",
        "operationId": "openInstanceConsole",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 19,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "The console URL.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "url"
                  ],
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`CONSOLE_INSTANCE_NOT_RUNNING`: the instance must be running to open its console. Start it, wait for the operation to succeed, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`CONSOLE_UNAVAILABLE`: the console is not available right now. Retry in a minute.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/volume-key-credential": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Issue a volume key credential",
        "description": "Gives an instance the **credential** it uses to ask Pantech for the key of an encrypted data volume. Put the credential on the instance, in the volume agent's configuration, and attach the volume to any instance of your organization: that instance can unlock the volume, whether it runs an encrypted image or a plain one. A volume's key is released only to an instance of the same organization that the volume is attached to.\n\n**The credential is a secret: it is shown once.** Pantech keeps only a hash of it, so it cannot be shown again. Treat it like a password and never log or share it. Each request issues a new credential and **ends the previous one** for that instance, so use it to rotate a credential too, and update the agent on that instance. The credential also ends when the instance is deleted.\n\n**Idempotency:** each request issues a new credential; a retry is not replayed.\n\n**Scope:** `write`.",
        "operationId": "issueVolumeKeyCredential",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 20,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "The new credential. It is shown once.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "instance_id",
                    "credential"
                  ],
                  "properties": {
                    "instance_id": {
                      "type": "string",
                      "examples": [
                        "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
                      ]
                    },
                    "credential": {
                      "type": "string",
                      "description": "The secret, `pvk_` followed by 43 characters. Shown once."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INSTANCE_NOT_LIVE`: the instance is being deleted or has failed. Use another instance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`ENCRYPTED_VOLUMES_UNAVAILABLE`: encrypted volumes are not available right now. Retry in a minute.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/metrics": {
      "get": {
        "tags": [
          "Instances"
        ],
        "summary": "Get instance metrics",
        "description": "CPU, memory, network and disk activity over `interval` (`1h`, `24h`, `7d` or `30d`), one point per bucket. `available` is false when no samples exist yet, for example just after creation.\n\n**Scope:** `read`.",
        "operationId": "getInstanceMetrics",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 24,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "interval",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1h",
                "24h",
                "7d",
                "30d"
              ],
              "default": "24h"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The series.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetricsSeries"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`interval` `INVALID_METRIC_INTERVAL`: use `1h`, `24h`, `7d` or `30d`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/reboot": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Reboot an instance",
        "description": "Restarts the instance (a clean reboot of the operating system). It must be running.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\nFor the first 5 minutes after a new instance is created, this returns `409` with code `INSTANCE_POWER_LOCKED` while first boot finishes. Wait the `Retry-After` header's seconds, then try again. Pending, provisioning, or uncertain instances also return this 409 before the first run is recorded, without `Retry-After`; wait for the instance to reach running first.\n\n**Scope:** `write`.",
        "operationId": "rebootInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 13,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the instance has been deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/rebuild": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Rebuild an instance",
        "description": "Reinstalls the operating system from `image_slug`, or from the instance's current image when it is left out. **Everything on the root disk is erased**; attached volumes, addresses and the plan are kept. Take a snapshot first if you may need the data.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "rebuildInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 16,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RebuildRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`ACCOUNT_NOT_ACTIVE`: the organization's billing account is not active yet. Finish billing setup in the console (verify the organization and add a payment method), then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`image_slug` `IMAGE_NOT_FOUND`: no active image has this slug. Pick one from `GET /public/v1/images`.\n`image_slug` `IMAGE_NOT_AVAILABLE_IN_ZONE`: the image does not run in this instance's zone. Pick an image whose `zones` include it.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/rename": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Rename an instance",
        "description": "Changes the instance's name (1 to 255 characters, unique among your instances).\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "renameInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 14,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INSTANCE_NAME_TAKEN`: you already have an instance with this name. Choose a different name.\n`ACCOUNT_NOT_ACTIVE`: the organization's billing account is not active yet. Finish billing setup in the console (verify the organization and add a payment method), then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/resize": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Resize an instance",
        "description": "Moves the instance to a bigger plan. The instance is stopped, resized and started again. Instances only grow: the new plan must be bigger than the current one. No upfront charge: the bigger plan is billed hourly from the change.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "resizeInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 15,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResizeRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`plan_slug` `PLAN_NOT_FOUND`: no active plan has this slug. Pick one from `GET /public/v1/plans`.\n`plan_slug` `PLAN_NOT_BIGGER`: the plan is not bigger than the instance's current one. Choose a bigger plan.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/change-ssh-key": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Change an instance's SSH key",
        "description": "Replaces the SSH key you log in to the instance with by another key on your account, for example after losing the private key. The instance must be running: it is stopped, given the new key and started again, which takes about two minutes. The previous key stops working once the instance is back. Keys you added to the server yourself are left as they are.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "changeInstanceSSHKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 18,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangeSSHKeyRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state: it is not running, or another change such as a resize is in progress. Start it, or wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`ssh_key_id` `REQUIRED`: the field is missing. Send the id of one of your SSH keys.\n`ssh_key_id` `SSH_KEY_NOT_FOUND`: no SSH key with this id on your account. Pick one from `GET /public/v1/ssh-keys`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/restore": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Restore an instance from a snapshot",
        "description": "Rolls the instance's root disk back to one of its own snapshots and reboots it. **Everything written to the root disk since the snapshot is lost**, so `confirm_name` must repeat the instance's current name. Attached volumes are not changed.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "restoreInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 17,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.\n`RESOURCE_NOT_FOUND` can also mean `snapshot_id` is not a snapshot of this instance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`ACCOUNT_NOT_ACTIVE`: the organization's billing account is not active yet. Finish billing setup in the console (verify the organization and add a payment method), then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`snapshot_id` `REQUIRED`: send a snapshot of this instance.\n`confirm_name` `REQUIRED` or `CONFIRM_NAME_MISMATCH`: repeat the instance's current name exactly.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/security-group": {
      "put": {
        "tags": [
          "Instances"
        ],
        "summary": "Change an instance's security group",
        "description": "Moves a standard instance to another of your security groups. The instance must be stopped; the new group applies when it starts again.\n\nIf the instance has a private database network interface, the new group must allow nothing from the private network's range (`10.250.0.0/20` in `af-abj-1`): a group with any ingress rule whose source overlaps it, `0.0.0.0/0` included, is refused.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "changeInstanceSecurityGroup",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 18,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangeSecurityGroupRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INSTANCE_MUST_BE_STOPPED`: stop the instance first; the new group is applied when it starts again.\n`SECURITY_GROUPS_NOT_SUPPORTED_IN_ZONE`: a VPC instance uses its subnet's firewall rules, not a security group.\n`ACCOUNT_NOT_ACTIVE`: the organization's billing account is not active yet. Finish billing setup in the console (verify the organization and add a payment method), then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`security_group_id` `REQUIRED` or `SECURITY_GROUP_NOT_FOUND`: send the id of one of your security groups.\n`security_group_id` `SECURITY_GROUP_ALLOWS_PRIVATE_NETWORK`: the group allows inbound traffic from the private database network, which this instance is attached to; the message names the range and the rules. Replace `0.0.0.0/0` (including the default group's ICMP rule) with narrower ranges that leave out the private range, then retry.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/private-network": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Add a private database network interface to an instance",
        "description": "Adds a second network interface on the zone's private database network to a standard instance, so it can reach your managed databases there by their private address. Only in a zone with a private database network (`af-abj-1`); a VPC instance already reaches databases in its own VPC. The interface is free.\n\nWhen the operation succeeds, the instance's `private_network_state` is `attached` and `private_network_ip` is the interface's address: allow it on each database as a `/32` access rule (*Replace access rules*).\n\n**The instance's security group must allow nothing from the private network's range** (`10.250.0.0/20`; the zone's `private_network_cidr` in `GET /public/v1/regions`). A security group applies to every interface of an instance, so any ingress rule whose source overlaps that range, whatever its protocol or ports, would let every database and every other customer's private interface on the network reach this instance. That includes `0.0.0.0/0` and `10.0.0.0/8`, and the ICMP-from-anywhere rule of your organization's default security group. Such a group is refused, naming the rules to change: replace `0.0.0.0/0` with the addresses you actually need, or with ranges that leave out `10.250.0.0/20`, or move the instance to a group without such rules. While the instance has the interface, rule changes and group moves that would allow the range are refused too.\n\nThe instance must be running or stopped with no other change in progress. A running instance gets the interface without a restart.\n\n**In the guest** the interface stays down until you configure it. On Ubuntu add it to netplan with DHCP only, never the default route or DNS: `dhcp4: true` with `dhcp4-overrides: {use-routes: false, use-dns: false}` for the new interface (often `ens4` or `eth1`), then run `netplan apply`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. If the operation fails, its `failure.code` says why: `SECURITY_GROUP_ALLOWS_PRIVATE_NETWORK` (a rule allowing the range was added meanwhile; nothing was attached), `INSTANCE_BUSY` (the instance kept changing; retry when it has settled), or `INSTANCE_PRIVATE_NETWORK_ATTACH_FAILED` (retry later, or contact support). The instance itself is never marked failed for it.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "attachInstancePrivateNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 102,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted; read the instance for private_network_ip once it succeeds",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "vm_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.\n`NOT_FOUND`: private database network interfaces are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PRIVATE_NETWORK_NOT_AVAILABLE`: this instance's zone has no private database network for instances (VPC instances reach databases in their own VPC). Nothing to attach.\n`SECURITY_GROUP_ALLOWS_PRIVATE_NETWORK`: the instance's security group allows inbound traffic from the private network's range; `detail` names the range and each offending rule. Replace `0.0.0.0/0` in those rules (including the default group's ICMP rule) with narrower ranges that leave out `10.250.0.0/20`, or move the instance to another group, then retry.\n`PRIVATE_NETWORK_ALREADY_ATTACHED`: the instance already has the interface, or it is being added. Read the instance for `private_network_ip`.\n`PRIVATE_NETWORK_CHANGE_IN_PROGRESS`: the interface is being added or removed. Wait for that operation to finish.\n`INSTANCE_NOT_SETTLED`: the instance is starting, stopping, resizing, restoring or being deleted. Wait until it is running or stopped, then retry.\n`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Instances"
        ],
        "summary": "Remove an instance's private database network interface",
        "description": "Removes the instance's interface on the private database network. The instance must be running or stopped with no other change in progress; a running instance keeps running. `private_network_ip` stays readable until the operation succeeds; then remove any database access rule for it, and the interface from the guest's network configuration.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. A detach that cannot complete fails with `INSTANCE_PRIVATE_NETWORK_DETACH_FAILED`; retry later.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "detachInstancePrivateNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 103,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "vm_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.\n`NOT_FOUND`: private database network interfaces are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PRIVATE_NETWORK_NOT_ATTACHED`: the instance has no private network interface to remove.\n`PRIVATE_NETWORK_CHANGE_IN_PROGRESS`: the interface is being added or removed. Wait for that operation to finish.\n`INSTANCE_NOT_SETTLED`: the instance is starting, stopping, resizing, restoring or being deleted. Wait until it is running or stopped, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/snapshot-schedule": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Get an instance's snapshot schedule",
        "description": "The instance's automatic snapshot schedule: how often a snapshot of its root disk is taken, how many are kept, and when the next one runs.\n\n**Scope:** `read`.",
        "operationId": "getInstanceSnapshotSchedule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 29,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The schedule.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotSchedule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.\n`SNAPSHOT_SCHEDULE_NOT_FOUND`: no schedule has been set for this resource. Set one with the `PUT` on this path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "put": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Set an instance's snapshot schedule",
        "description": "Turns automatic snapshots of the root disk on, changes them, or pauses them with `enabled: false`. `frequency` is `daily`, `weekly` or `monthly`; `retention_count` (1 to 168, default 7) successful snapshots are kept and older automatic ones are deleted. Automatic snapshots are billed like manual ones.\n\nReturns the schedule at once (`200`); no operation to follow. Send an `Idempotency-Key`: a retry with the same key and settings returns the same schedule.\n\n**Scope:** `write`. Lowering `retention_count` deletes the oldest copies, so an AI app's key also needs `delete` for that (`403 INSUFFICIENT_SCOPE` otherwise).",
        "operationId": "putInstanceSnapshotSchedule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 30,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutSnapshotScheduleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The schedule.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotSchedule"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`IDEMPOTENCY_CONFLICT`: this `Idempotency-Key` was already used with different settings. Use a new key for a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`frequency` `REQUIRED`: send `daily`, `weekly` or `monthly`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: `frequency` is not `daily`, `weekly` or `monthly`, or `retention_count` is outside 1 to 168.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/snapshots": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "List an instance's snapshots",
        "description": "Snapshots of this instance's root disk, oldest first.\n\n**Scope:** `read`.",
        "operationId": "listInstanceSnapshots",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 27,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of snapshots.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Snapshot an instance",
        "description": "Takes a snapshot of the instance's root disk, named `name` (unique among this instance's snapshots). A snapshot of a running instance is crash-consistent: what the disk held at that instant. Billed on its physical size, hourly, until deleted.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The new snapshot's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createInstanceSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 28,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSnapshotRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`SNAPSHOT_NAME_TAKEN`: this instance already has a snapshot with that name. Choose a different name.\n`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/ssh-access": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Grant temporary SSH access",
        "description": "Opens port 22 of a standard instance to the address this request comes from, for 15 minutes, so you can SSH in without leaving the port open. The instance must be running and be the only one using its security group.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. Then read the grant (`GET /public/v1/instances/{instance_id}/ssh-access/{grant_id}`, the operation's `resource_id` is the grant id) for the `host` and `port` to connect to once `status` is `active`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "openSSHAccess",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 20,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_CALLER_ADDRESS`: the address this request comes from could not be used to scope access. Retry from a normal internet connection.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`SSH_ACCESS_INSTANCE_NOT_RUNNING`: the instance must be running. Start it, then retry.\n`SSH_ACCESS_SECURITY_GROUP_SHARED`: the instance's security group is used by other instances too, so opening it would open them all. Move the instance to its own security group, then retry.\n`SSH_ACCESS_NOT_SUPPORTED_IN_ZONE`: temporary SSH access is not available for VPC instances yet. Use a public IP with a port forwarding rule instead.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/ssh-access/{grant_id}": {
      "get": {
        "tags": [
          "Instances"
        ],
        "summary": "Get an SSH access grant",
        "description": "A temporary SSH access grant: its `status`, and the `host` and `port` to connect to once it is `active`. It expires by itself at `expires_at`.\n\n**Scope:** `read`.",
        "operationId": "getSSHAccess",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 21,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "grant_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The grant.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SSHAccessGrant"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no grant with this id on this instance, or the instance is not in your organization. Check both ids.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Instances"
        ],
        "summary": "Revoke SSH access",
        "description": "Closes the port opened by a grant before it expires.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "revokeSSHAccess",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 22,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "grant_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no grant with this id on this instance, or the instance is not in your organization. Check both ids.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the grant is already revoked or expired. Nothing to do.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/start": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Start an instance",
        "description": "Starts a stopped instance. A running instance is billed for its plan again.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "startInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 11,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the instance has been deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/stop": {
      "post": {
        "tags": [
          "Instances"
        ],
        "summary": "Stop an instance",
        "description": "Shuts the instance down. A stopped instance keeps its disks and addresses and is billed for storage only.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\nFor the first 5 minutes after a new instance is created, this returns `409` with code `INSTANCE_POWER_LOCKED` while first boot finishes. Wait the `Retry-After` header's seconds, then try again. Pending, provisioning, or uncertain instances also return this 409 before the first run is recorded, without `Retry-After`; wait for the instance to reach running first.\n\n**Scope:** `write`.",
        "operationId": "stopInstance",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 12,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the instance cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the instance has been deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get an instance's usage",
        "description": "Measured usage for this instance in the current billing period: running hours, storage, memory and network.\n\n**Scope:** `read`.",
        "operationId": "getInstanceUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 25,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/instances/{instance_id}/volumes": {
      "get": {
        "tags": [
          "Volumes"
        ],
        "summary": "List an instance's volumes",
        "description": "The volumes attached to this instance.\n\n**Scope:** `read`.",
        "operationId": "listInstanceVolumes",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 26,
        "parameters": [
          {
            "name": "instance_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of volumes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VolumeList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no instance with this id in your organization, or the id is not a instance id (`vm_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Describe this API key",
        "description": "The organization and project the key acts in, its scopes and when it expires. Call it to check that a key works before using it.\n\n**Scope:** `read`.",
        "operationId": "getMe",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 1,
        "responses": {
          "200": {
            "description": "The key.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Account"
        ],
        "summary": "Revoke this API key",
        "description": "Revokes the API key that sends this request, at once and for good. This is how an AI app disconnects itself and how `pantech auth logout` ends its key. Other keys are untouched.\n\nIt needs no `Idempotency-Key`: once the key is revoked, repeating the call gets `401 UNAUTHENTICATED`, because the key no longer works. It works even while the organization has AI app access turned off.\n\n**Scope:** `read` (any key may revoke itself).",
        "operationId": "revokeMe",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 2,
        "responses": {
          "204": {
            "description": "The key is revoked."
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/networks": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "List VPC networks",
        "description": "Your VPC networks, newest first. Filter by name with `q`, or by state.\n\n**Scope:** `read`.",
        "operationId": "listNetworks",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 33,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of networks.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Networks"
        ],
        "summary": "Create a VPC network",
        "description": "Creates a VPC: a private network of your own, with a CIDR such as `10.0.0.0/16`. Then add subnets to it, and instances or databases to the subnets. A VPC is billed monthly: see *Price a VPC network*.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The network's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 34,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateNetworkRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`NETWORK_NAME_TAKEN`: you already have a VPC with this name. Choose a different name.\n`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`PROVIDER_ACCOUNT_NOT_READY`: your organization's cloud account is still being set up, which takes a few minutes after sign-up. Retry shortly.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`cidr` `REQUIRED`: send an IPv4 CIDR such as `10.0.0.0/16`.\n`region` `REGION_NOT_AVAILABLE`: this region cannot take VPC networks now. Pick one from `GET /public/v1/regions`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: `cidr` is not a valid IPv4 CIDR.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/networks/quote": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "Price a VPC network",
        "description": "What one more VPC network costs per month, in your organization's currency. `priced` is false, with an `unpriced_reason`, when no price applies.\n\n**Scope:** `read`.",
        "operationId": "quoteNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 35,
        "responses": {
          "200": {
            "description": "The price.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonthlyQuote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: cost quotes are not available on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/networks/{network_id}": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "Get a VPC network",
        "description": "One VPC network, with the number of instances in it.\n\n**Scope:** `read`.",
        "operationId": "getNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 36,
        "parameters": [
          {
            "name": "network_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The network.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Network"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no VPC network with this id in your organization, or the id is not a VPC network id (`net_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Networks"
        ],
        "summary": "Delete a VPC network",
        "description": "Deletes a VPC network. It must hold no instances (in any of its subnets) and no public IPs.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 37,
        "parameters": [
          {
            "name": "network_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no VPC network with this id in your organization, or the id is not a VPC network id (`net_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`NETWORK_HAS_INSTANCES`: a subnet of this network still has instances. Delete or move them first.\n`NETWORK_HAS_PUBLIC_IPS`: the network still holds public IPs. Release them first.\n`INVALID_RESOURCE_STATE`: the network cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused a value, for example a malformed CIDR or a name longer than 255 characters. Check the request against this page.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/networks/{network_id}/subnets": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "List subnets",
        "description": "The VPC's subnets.\n\n**Scope:** `read`.",
        "operationId": "listSubnets",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 38,
        "parameters": [
          {
            "name": "network_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of subnets.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubnetList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no VPC network with this id in your organization, or the id is not a VPC network id (`net_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Networks"
        ],
        "summary": "Create a subnet",
        "description": "Creates a subnet inside the VPC's CIDR, such as `10.0.1.0/24`. Instances and databases are placed in subnets; each subnet has its own firewall rules.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The subnet's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createSubnet",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 39,
        "parameters": [
          {
            "name": "network_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSubnetRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no VPC network with this id in your organization, or the id is not a VPC network id (`net_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the network cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`cidr` `REQUIRED`: send an IPv4 CIDR inside the VPC's CIDR.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: `cidr` is not a valid IPv4 CIDR.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/operations/{operation_id}": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Get an operation",
        "description": "One asynchronous operation. Every write that returns `202` gives you its `operation_id`: poll this until `status` is `succeeded` or `failed` (wait a second or two between polls), or use *Stream an operation* instead.\n\nA failed operation has `failure.code`, a stable code to branch on, and `failure.reason`, a readable sentence safe to show to your users.\n\n**Scope:** `read`.",
        "operationId": "getOperation",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 82,
        "parameters": [
          {
            "name": "operation_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The operation.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Operation"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no operation with this id in your organization, or the id is not a operation id (`op_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/operations/{operation_id}/events": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Stream an operation",
        "description": "Server-Sent Events for one operation: an `operation` event (data: the Operation) each time it changes, ending when it succeeds or fails. A `: keepalive` comment is sent while it is idle. Use it instead of polling.\n\nIf the stream stops before the operation finishes, its last event is `error`, with data `{\"code\", \"detail\", \"request_id\"}`: `OPERATION_STREAM_UNAVAILABLE` after 30 seconds of failing to read the operation, `UNAUTHENTICATED` within 30 seconds of the key being revoked or expiring, or `OPERATION_STREAM_TIMEOUT` after 15 minutes open. Reconnect, or poll `GET /public/v1/operations/{operation_id}`.\n\n**Scope:** `read`.",
        "operationId": "streamOperation",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 83,
        "parameters": [
          {
            "name": "operation_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The event stream.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no operation with this id in your organization, or the id is not a operation id (`op_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/plans": {
      "get": {
        "tags": [
          "Catalogue"
        ],
        "summary": "List plans",
        "description": "Instance sizes (vCPU, memory and disk), priced in your organization's currency. Use a `slug` as `plan_slug` for an instance or a database. Send `placement=vpc` to price a VPC instance (no public address of its own), or leave it out for a standard instance.\n\n**Scope:** `read`.",
        "operationId": "listPlans",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 3,
        "parameters": [
          {
            "name": "placement",
            "in": "query",
            "description": "Price for standard instances or VPC instances.",
            "schema": {
              "type": "string",
              "enum": [
                "standard",
                "vpc"
              ],
              "default": "standard"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Plans.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`placement` `INVALID_PLACEMENT`: use `standard` or `vpc`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/load-balancers": {
      "get": {
        "tags": [
          "Load balancers"
        ],
        "summary": "List load balancers",
        "description": "Your load balancers, newest first, each with its targets. Deleted and failed ones are left out. Narrow it with `network_id` or `public_ip_id`.\n\n**Scope:** `read`.",
        "operationId": "listLoadBalancers",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 110,
        "parameters": [
          {
            "name": "network_id",
            "in": "query",
            "required": false,
            "description": "Only load balancers in this private network (`net_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "public_ip_id",
            "in": "query",
            "required": false,
            "description": "Only load balancers on this public IP (`pip_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The load balancers.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoadBalancerList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: load balancers are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Load balancers"
        ],
        "summary": "Create a load balancer",
        "description": "Spreads one TCP port of a `load_balancer` public IP across instances in one subnet of that IP's private network (VPC). The public IP must be active and have `purpose` `load_balancer`; one public IP can carry several load balancers, one per public port. `private_port` defaults to `public_port`, and `algorithm` to `roundrobin`. `cidr_list` limits which source addresses may connect (default: anywhere). The subnet's firewall rules must allow the port.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice. The load balancer's id is the operation's `resource_id`.\n\n**Scope:** `write`.",
        "operationId": "createLoadBalancer",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 111,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLoadBalancerRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: the public IP, subnet or an instance does not exist in your organization. Check the ids.\n`NOT_FOUND`: load balancers are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PUBLIC_IP_NOT_FOR_LOAD_BALANCER`: use an active public IP with `purpose` `load_balancer`.\n`PORT_IN_USE`: another load balancer on this public IP already uses this port. Choose another port, or delete that load balancer.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name`, `public_ip_id`, `subnet_id` or `public_port` `REQUIRED`: send them.\n`public_port` `INVALID_LOAD_BALANCER`: `name` 1 to 63 characters, `algorithm` `roundrobin`, `leastconn` or `source`, ports 1 to 65535, and at most 20 IPv4 CIDRs in `cidr_list`.\n`subnet_id` `SUBNET_NOT_IN_NETWORK`: the subnet is not in the public IP's private network.\n`instance_ids` `INSTANCE_NOT_IN_SUBNET`: every instance must be in the load balancer's subnet.\n`instance_ids` `TOO_MANY`: at most 50 instances.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/load-balancers/{load_balancer_id}": {
      "get": {
        "tags": [
          "Load balancers"
        ],
        "summary": "Get a load balancer",
        "description": "One load balancer, with its targets. `in_sync` is false while a change you made has not reached it yet.\n\n**Scope:** `read`.",
        "operationId": "getLoadBalancer",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 112,
        "parameters": [
          {
            "name": "load_balancer_id",
            "in": "path",
            "required": true,
            "description": "The load balancer's id (`lb_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The load balancer.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoadBalancer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no load balancer with this id in your organization, or the id is not a load balancer id (`lb_…`). Check the id.\n`NOT_FOUND`: load balancers are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "patch": {
        "tags": [
          "Load balancers"
        ],
        "summary": "Change a load balancer",
        "description": "Renames it, changes its `algorithm`, or replaces its targets: `instance_ids`, when sent (even empty), is the whole new set. Fields you leave out stay as they are. The ports, the public IP, the subnet and `cidr_list` cannot change: create a new load balancer for those. A change that changes nothing returns an empty `operation_id`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "updateLoadBalancer",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 113,
        "parameters": [
          {
            "name": "load_balancer_id",
            "in": "path",
            "required": true,
            "description": "The load balancer's id (`lb_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLoadBalancerRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no load balancer with this id in your organization, or the id is not a load balancer id (`lb_…`). Check the id.\n`NOT_FOUND`: load balancers are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`LOAD_BALANCER_NOT_CHANGEABLE`: the load balancer is being deleted or has failed.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`public_port` `INVALID_LOAD_BALANCER`: `name` 1 to 63 characters and `algorithm` `roundrobin`, `leastconn` or `source`.\n`instance_ids` `INSTANCE_NOT_IN_SUBNET`: every instance must be in the load balancer's subnet.\n`instance_ids` `TOO_MANY`: at most 50 instances.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Load balancers"
        ],
        "summary": "Delete a load balancer",
        "description": "Deletes the load balancer. Traffic to its port stops once the operation succeeds; the instances and the public IP are kept.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteLoadBalancer",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 114,
        "parameters": [
          {
            "name": "load_balancer_id",
            "in": "path",
            "required": true,
            "description": "The load balancer's id (`lb_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no load balancer with this id in your organization, or the id is not a load balancer id (`lb_…`). Check the id.\n`NOT_FOUND`: load balancers are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/port-forwarding-rules/{rule_id}": {
      "delete": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Delete a port forwarding rule",
        "description": "Deletes one port forwarding rule. Traffic to those ports stops once the operation succeeds.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deletePortForwardingRule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 54,
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "description": "The rule's id (`aclr_...` for a firewall rule, `pfr_...` for a port forwarding rule).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no port forwarding rule with this id in your organization, or the id is not a port forwarding rule id (`pfr_…`). Check the id.\n`NOT_FOUND`: port forwarding is not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the port forwarding rule cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/pricing/estimate": {
      "post": {
        "tags": [
          "Catalogue"
        ],
        "summary": "Estimate a monthly bill",
        "description": "Prices a whole configuration before you build it: machines by plan and running hours, extra storage, VPC networks and snapshot storage. Nothing is created and nothing is charged, so no `Idempotency-Key` is needed.\n\n`pricing_complete` is false when any line could not be priced; that line has `priced: false` and an `unpriced_reason`.\n\n**Scope:** `read`.",
        "operationId": "estimatePricing",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 7,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PricingEstimateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The estimate.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricingEstimate"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`currency` `UNSUPPORTED_CURRENCY`: use `NGN` or `USD`.\n`machines` `TOO_MANY_MACHINES`: at most 50 machine lines.\n`machines` `INVALID_MACHINE`: each machine needs a `plan_slug`, a `quantity` above 0 and 0 to 730 `running_hours`.\n`placement` `INVALID_PLACEMENT`: use `standard` or `vpc`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/public-ips": {
      "get": {
        "tags": [
          "Public IPs"
        ],
        "summary": "List public IPs",
        "description": "Your VPC public IPs, or one VPC's with `network_id`.\n\n**Scope:** `read`.",
        "operationId": "listPublicIPs",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 46,
        "parameters": [
          {
            "name": "network_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Public IPs.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicIPList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: public IPs are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Allocate a public IP",
        "description": "Allocates a public IPv4 address for a VPC. `static_nat` (the default) maps every port of the address to one instance in `network_id`, sent as `instance_id`; `port_forwarding`, where offered, carries per-port rules instead (add them with *Add a port forwarding rule*). The network must be active. A public IP is billed monthly: see *Price a public IP*.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The address is in the public IP's `address` once it succeeds.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createPublicIP",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 47,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePublicIPRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE`: this API key has only the `read` scope. Use a key with `write` access.\n`FORBIDDEN`: the member who created this key may not do this in the organization, or has left it. Use a key created by an owner or admin.\n`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server. An owner can turn it on in the console under Organization › AI apps.\n`STATIC_NAT_LIMIT_EXCEEDED`: your organization has reached its limit of static NAT public IPs. Release one you no longer need, or contact support for a higher limit.\n`PUBLIC_IP_LIMIT_EXCEEDED`: your organization has reached its limit of public IPs of any purpose (20 by default). Release one you no longer need, or contact support for a higher limit.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`: public IPs are not offered on this platform yet.\n`RESOURCE_NOT_FOUND`: `network_id` is not one of your VPC networks.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`NETWORK_NOT_READY`: public IPs can only be added to an active VPC network. Wait for the network to be active.\n`INSTANCE_ALREADY_HAS_PUBLIC_IP`: the instance already has a public IP. Release it before adding another.\n`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`network_id` `REQUIRED`: send the VPC network.\n`purpose` `PURPOSE_NOT_AVAILABLE`: use `static_nat`, `port_forwarding` or `load_balancer`.\n`instance_id` `INSTANCE_NOT_IN_NETWORK`: the instance is not in `network_id`.\n`instance_id` `NOT_ALLOWED`: a `port_forwarding` address takes no instance; each rule names its own.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/public-ips/quote": {
      "get": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Price a public IP",
        "description": "What one more public IP costs per month, in your organization's currency.\n\n**Scope:** `read`.",
        "operationId": "quotePublicIP",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 48,
        "responses": {
          "200": {
            "description": "The price.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonthlyQuote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: cost quotes are not available on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/public-ips/{public_ip_id}": {
      "get": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Get a public IP",
        "description": "One public IP, with the instance it maps to.\n\n**Scope:** `read`.",
        "operationId": "getPublicIP",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 49,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The public IP.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicIP"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no public IP with this id in your organization, or the id is not a public IP id (`pip_…`). Check the id.\n`NOT_FOUND`: public IPs are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Release a public IP",
        "description": "Releases a public IP. The address is returned to the pool and may be given to someone else; billing stops when the operation succeeds. Delete its port forwarding rules first.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deletePublicIP",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 50,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no public IP with this id in your organization, or the id is not a public IP id (`pip_…`). Check the id.\n`NOT_FOUND`: public IPs are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PUBLIC_IP_HAS_PORT_FORWARDS`: delete this address's port forwarding rules first.\n`PUBLIC_IP_HAS_LOAD_BALANCERS`: delete this address's load balancers first.\n`INVALID_RESOURCE_STATE`: the public IP cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/public-ips/{public_ip_id}/attach": {
      "post": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Attach a public IP to an instance",
        "description": "Points a static NAT public IP at an instance in the same private network (VPC), keeping the address. Use it to move an address from one instance to another without releasing it: you keep the same IP and pay for it once. If the address is attached elsewhere it moves; the instance must not already have a static NAT address of its own.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). Poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`. While it runs the address shows `in_sync: false`. Send an `Idempotency-Key`; a change that changes nothing returns an empty `operation_id`.\n\n**Scope:** `write`.",
        "operationId": "attachPublicIP",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 51,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachPublicIPRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no public IP with this id in your organization, or the id is not a public IP id (`pip_…`). Check the id.\n`NOT_FOUND`: public IPs are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PUBLIC_IP_NOT_STATIC_NAT`: only a static NAT address can be attached or detached; port forwarding and load balancer addresses use their rules.\n`INSTANCE_ALREADY_HAS_PUBLIC_IP`: the instance already has a static NAT address. Detach or release that one first.\n`INVALID_RESOURCE_STATE`: the public IP cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: `instance_id` `REQUIRED`, or `INSTANCE_NOT_IN_NETWORK` (the instance must be in the address's private network). With no `errors` entry: the platform refused the request, for example because the instance is deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/public-ips/{public_ip_id}/detach": {
      "post": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Detach a public IP from its instance",
        "description": "Unmaps a static NAT public IP from its instance. The address stays yours (and is billed once, as before) until you attach it to another instance or release it. The instance keeps running and can then be deleted.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). Poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`. While it runs the address shows `in_sync: false`. Send an `Idempotency-Key`; a change that changes nothing returns an empty `operation_id`.\n\n**Scope:** `write`.",
        "operationId": "detachPublicIP",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 52,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no public IP with this id in your organization, or the id is not a public IP id (`pip_…`). Check the id.\n`NOT_FOUND`: public IPs are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PUBLIC_IP_NOT_STATIC_NAT`: only a static NAT address can be attached or detached; port forwarding and load balancer addresses use their rules.\n`INVALID_RESOURCE_STATE`: the public IP cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/public-ips/{public_ip_id}/port-forwarding-rules": {
      "get": {
        "tags": [
          "Public IPs"
        ],
        "summary": "List port forwarding rules",
        "description": "The address's port forwarding rules.\n\n**Scope:** `read`.",
        "operationId": "listPortForwardingRules",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 51,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rules.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortForwardingRuleList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no public IP with this id in your organization, or the id is not a public IP id (`pip_…`). Check the id.\n`NOT_FOUND`: port forwarding is not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Add a port forwarding rule",
        "description": "Forwards a port or range of a `port_forwarding` public IP to an instance in its VPC. Defaults: `public_port_end` equals `public_port_start`, and the private range equals the public one (or starts at `private_port_start` with the same width).\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The rule's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createPortForwardingRule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 52,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePortForwardingRuleRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no public IP with this id in your organization, or the id is not a public IP id (`pip_…`). Check the id.\n`NOT_FOUND`: port forwarding is not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PUBLIC_IP_NOT_FOR_PORT_FORWARDING`: use an active public IP with `purpose` `port_forwarding`.\n`PORTS_IN_USE`: another rule on this address already forwards some of these ports for this protocol. Choose other ports, or delete that rule.\n`INVALID_RESOURCE_STATE`: the public IP cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`instance_id` or `protocol` `REQUIRED`: send both.\n`instance_id` `INSTANCE_NOT_IN_NETWORK`: the instance is not in the address's VPC.\n`public_port_start` `INVALID_PORTS`: use `tcp` or `udp`, ports 1 to 65535, and public and private ranges of the same width.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/public-ips/{public_ip_id}/port-forwarding-rules/{rule_id}": {
      "get": {
        "tags": [
          "Public IPs"
        ],
        "summary": "Get a port forwarding rule",
        "description": "One port forwarding rule on the address.\n\n**Scope:** `read`.",
        "operationId": "getPortForwardingRule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 53,
        "parameters": [
          {
            "name": "public_ip_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "description": "The rule's id (`aclr_...` for a firewall rule, `pfr_...` for a port forwarding rule).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rule.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortForwardingRule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no rule with this id on this address, or no such address in your organization. Check both ids.\n`NOT_FOUND`: port forwarding is not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/regions": {
      "get": {
        "tags": [
          "Catalogue"
        ],
        "summary": "List regions",
        "description": "Regions and their zones, and whether each zone can take standard instances or VPC networks right now (`available`, with an `unavailable_reason` when not). Use a zone as `zone_id` for a database, or a region as `region` elsewhere.\n\n**Scope:** `read`.",
        "operationId": "listRegions",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 2,
        "responses": {
          "200": {
            "description": "Regions.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegionList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/kubernetes-versions": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "List Kubernetes versions",
        "description": "The Kubernetes versions you can create clusters with, newest first, each in one zone. `ha_zone_ids` are the zones where a highly available control plane (3 control nodes) can be created now. A version is withdrawn from new clusters before its upstream end of life; clusters already on it keep running it.\n\n**Scope:** `read`.",
        "operationId": "listKubernetesVersions",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 115,
        "parameters": [
          {
            "name": "zone_id",
            "in": "query",
            "required": false,
            "description": "Only versions in this zone.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The versions.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KubernetesVersionList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "List Kubernetes clusters",
        "description": "Your Kubernetes clusters, newest first. Deleted and failed clusters are left out.\n\n**Scope:** `read`.",
        "operationId": "listKubernetesClusters",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 116,
        "responses": {
          "200": {
            "description": "The clusters.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KubernetesClusterList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Create a Kubernetes cluster",
        "description": "Creates a managed Kubernetes cluster. Every node, control and worker, is a VM of `node_plan` in your account and is billed as one; there is no separate control-plane fee. In a VPC zone the nodes go in `subnet_id`; in a standard zone leave `subnet_id` out. `control_nodes` is 1, or 3 where the zone offers a highly available control plane (see `ha_zone_ids` on the versions list). Persistent volumes work out of the box. Download the kubeconfig once the cluster is `running`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice. The cluster's id is the operation's `resource_id`.\n\n**Scope:** `write`.",
        "operationId": "createKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 117,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKubernetesClusterRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "description": "`INSUFFICIENT_CREDIT`: your credit does not cover the first payment for every node. Top up or add a card, then try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NAME_TAKEN`: you already have a cluster with this name.\n`KUBERNETES_CLUSTER_LIMIT`: your organization has reached its cluster limit. Delete a cluster, or contact support to raise it.\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name`, `zone_id`, `kubernetes_version_id`, `node_plan` or `workers` `REQUIRED`: send them.\n`name` `INVALID_KUBERNETES_CLUSTER_NAME`: 1 to 40 lowercase letters, digits and hyphens, starting with a letter.\n`zone_id` `INVALID_KUBERNETES_ZONE`: a zone your organization can use.\n`kubernetes_version_id` `INVALID_KUBERNETES_VERSION`: a version offered in this zone.\n`node_plan` `INVALID_KUBERNETES_NODE_PLAN`: an active plan with at least the version's minimum vCPU and memory.\n`workers` `INVALID_KUBERNETES_WORKER_COUNT`: 1 to 10.\n`control_nodes` `INVALID_KUBERNETES_CONTROL_NODES` or `KUBERNETES_HA_NOT_AVAILABLE`: 1, or 3 where offered.\n`autoscaling` `INVALID_KUBERNETES_AUTOSCALING`: min_workers and max_workers 1 to 10, min no more than max, and workers within them.\n`api_allowed_cidrs` `INVALID_API_ALLOWED_CIDRS` (at most 20 IPv4 CIDRs) or `API_ALLOWED_CIDRS_VPC_ONLY`.\n`subnet_id` `KUBERNETES_SUBNET_REQUIRED`, `KUBERNETES_SUBNET_NOT_ALLOWED` or `KUBERNETES_SUBNET_NOT_FOUND`: an active subnet in a VPC zone, and none in a standard zone.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Get a Kubernetes cluster",
        "description": "One cluster. `in_sync` is false while a change you made has not reached it yet; `available_upgrades` lists the versions it can move to now.\n\n**Scope:** `read`.",
        "operationId": "getKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 118,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The cluster.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KubernetesCluster"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Change a Kubernetes cluster",
        "description": "Sets a fixed number of worker nodes (1 to 10), turns the cluster autoscaler on or off and sets its range, or replaces the list of addresses allowed to reach the API server (VPC zone). Send any of them; the rest stay as they are. The cluster must be running. Added workers, and an autoscaler maximum above today's count, are checked against your credit and account limits; workers are billed as VMs of the node plan while they run. A change that changes nothing returns an empty `operation_id`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "scaleKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 119,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateKubernetesClusterRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "description": "`INSUFFICIENT_CREDIT`: your credit does not cover the added nodes.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`: start the cluster first.\n`KUBERNETES_CLUSTER_BUSY`: the cluster is already changing. Wait until it is running or stopped.\n`KUBERNETES_CLUSTER_NOT_CHANGEABLE`: the cluster cannot make this change now (stopped, being deleted, or failed).\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: `workers` `REQUIRED` (send at least one field) or `INVALID_KUBERNETES_WORKER_COUNT` (1 to 10); `autoscaling` `INVALID_KUBERNETES_AUTOSCALING`; `api_allowed_cidrs` `INVALID_API_ALLOWED_CIDRS` or `API_ALLOWED_CIDRS_VPC_ONLY`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Delete a Kubernetes cluster",
        "description": "Deletes the cluster. It stops at once, disappears from your lists and stops billing; its nodes and disks are destroyed 12 hours later and cannot be recovered. Volumes your workloads created through persistent volume claims are deleted with it. Deleting a cluster already being deleted returns an empty `operation_id`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 120,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/upgrade": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Upgrade a Kubernetes cluster",
        "description": "Moves the cluster to a newer Kubernetes version: one of its `available_upgrades` (the next patch, or the next minor version). Upgrades never happen on their own and never go down. The cluster must be running; nodes are replaced one at a time.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "upgradeKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 121,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpgradeKubernetesClusterRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`: start the cluster first.\n`KUBERNETES_CLUSTER_BUSY`: the cluster is already changing. Wait until it is running or stopped.\n`KUBERNETES_CLUSTER_NOT_CHANGEABLE`: the cluster cannot make this change now (stopped, being deleted, or failed).\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: `kubernetes_version_id` `REQUIRED`, `INVALID_KUBERNETES_VERSION` or `KUBERNETES_UPGRADE_NOT_ALLOWED` (pick one of `available_upgrades`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/resize-plan": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Resize worker node compute plan",
        "description": "Resizes the compute plan of worker nodes in the cluster via zero-downtime rolling replacement.\nA new worker node with the updated plan is provisioned, joins the cluster, workloads migrate, and the old node is retired.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "resizeKubernetesClusterPlan",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 122,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResizeKubernetesClusterPlanRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`: start the cluster first.\n`KUBERNETES_CLUSTER_BUSY`: the cluster is already changing. Wait until it is running or stopped.\n`KUBERNETES_CLUSTER_NOT_CHANGEABLE`: the cluster cannot make this change now (stopped, being deleted, or failed).\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: `node_plan` `REQUIRED` or `INVALID_KUBERNETES_NODE_PLAN`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/upgrade-network": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Upgrade Kubernetes cluster networking",
        "description": "Reconfigures the CNI plugin (`flannel`, `wireguard`, `calico`), Pod CIDR, Service CIDR, or API allowed CIDR ranges for the cluster.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "upgradeKubernetesClusterNetwork",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 123,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpgradeKubernetesNetworkRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`: start the cluster first.\n`KUBERNETES_CLUSTER_BUSY`: the cluster is already changing. Wait until it is running or stopped.\n`KUBERNETES_CLUSTER_NOT_CHANGEABLE`: the cluster cannot make this change now (stopped, being deleted, or failed).\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: `INVALID_KUBERNETES_CNI_PLUGIN` or `INVALID_KUBERNETES_CIDR`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/start": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Start a Kubernetes cluster",
        "description": "Starts a stopped cluster. Its nodes are billed for compute again once it runs.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "startKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 122,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_BUSY`: the cluster is already changing. Wait until it is running or stopped.\n`KUBERNETES_CLUSTER_NOT_CHANGEABLE`: the cluster cannot make this change now (stopped, being deleted, or failed).\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/stop": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Stop a Kubernetes cluster",
        "description": "Stops a running cluster. While stopped only its disks are billed.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "stopKubernetesCluster",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 123,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_BUSY`: the cluster is already changing. Wait until it is running or stopped.\n`KUBERNETES_CLUSTER_NOT_CHANGEABLE`: the cluster cannot make this change now (stopped, being deleted, or failed).\n`CONCURRENT_UPDATE`: the cluster changed while this request was being processed. Retry the request; if it repeats, read the cluster first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/kubeconfig": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Download a kubeconfig",
        "description": "The cluster's admin kubeconfig, for `kubectl`. It holds a long-lived cluster-admin credential: store it like a password. It is fetched fresh on each call and is not kept by the platform. Available while the cluster is running. It is a `POST` that needs a `write` key so that a read-only key can never fetch a cluster-admin credential; the response is `Cache-Control: no-store`.\n\n**Scope:** `write`.",
        "operationId": "getKubernetesKubeconfig",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 124,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The kubeconfig.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Kubeconfig"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`: no cluster with this id in your organization. Check the id.\n`RESOURCE_NOT_FOUND`: the id is not a cluster id (`k8s_…`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBECONFIG_UNAVAILABLE`: the cluster is not running yet. Wait until it is, then try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`KUBERNETES_UNAVAILABLE`: managed Kubernetes is not open on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/nodes": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "List a cluster's nodes",
        "description": "The cluster's nodes as Kubernetes reports them right now, read from the cluster's own API server. `vcpu` and `memory_mb` are each node's capacity; `disk_gb` is the cluster's node plan.\n\nErrors: `404 KUBERNETES_CLUSTER_NOT_FOUND`; `409 KUBERNETES_CLUSTER_NOT_RUNNING` (start the cluster first); `503 KUBERNETES_API_UNREACHABLE` (the API server did not answer: it may still be starting, or its endpoint may be private; retry).",
        "operationId": "listKubernetesClusterNodes",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The cluster's nodes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "nodes"
                  ],
                  "properties": {
                    "nodes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "name",
                          "role",
                          "status",
                          "ip_address",
                          "vcpu",
                          "memory_mb",
                          "disk_gb",
                          "kubelet_version",
                          "created_at"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The node's name, which is its id inside Kubernetes."
                          },
                          "name": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "control",
                              "worker"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "Ready",
                              "NotReady"
                            ]
                          },
                          "ip_address": {
                            "type": "string",
                            "description": "The node's internal address."
                          },
                          "vcpu": {
                            "type": "integer"
                          },
                          "memory_mb": {
                            "type": "integer"
                          },
                          "disk_gb": {
                            "type": "integer"
                          },
                          "kubelet_version": {
                            "type": "string",
                            "examples": [
                              "v1.31.2+k3s1"
                            ]
                          },
                          "created_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`KUBERNETES_API_UNREACHABLE`: retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/workloads": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Get a cluster's services and pods",
        "description": "Every Service and pod in the cluster, in every namespace, read live from its API server. A cluster you have not deployed anything to shows only what Kubernetes itself runs. A service you exposed (see *Expose a Kubernetes service*) has `public_port` and `external_url`, the address it is reached on from the internet.\n\nErrors: `404 KUBERNETES_CLUSTER_NOT_FOUND`; `409 KUBERNETES_CLUSTER_NOT_RUNNING`; `503 KUBERNETES_API_UNREACHABLE` (retry).",
        "operationId": "getKubernetesWorkloads",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The cluster's services and pods.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "cluster_id",
                    "public_ip",
                    "api_port",
                    "services",
                    "pods"
                  ],
                  "properties": {
                    "cluster_id": {
                      "type": "string"
                    },
                    "public_ip": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The public address exposed services and the API server are reached on; null until routing has been synced."
                    },
                    "api_port": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "The cluster's API server port on `public_ip`; null for a private endpoint or before routing is synced."
                    },
                    "services": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "name",
                          "namespace",
                          "type",
                          "cluster_ip",
                          "external_ip",
                          "ports",
                          "public_port",
                          "external_url",
                          "created_at"
                        ],
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "namespace": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string",
                            "examples": [
                              "ClusterIP",
                              "NodePort",
                              "LoadBalancer"
                            ]
                          },
                          "cluster_ip": {
                            "type": "string"
                          },
                          "external_ip": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ports": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "name",
                                "protocol",
                                "port"
                              ],
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "protocol": {
                                  "type": "string"
                                },
                                "port": {
                                  "type": "integer"
                                },
                                "target_port": {
                                  "type": "integer",
                                  "description": "Left out when the target is a named container port."
                                },
                                "node_port": {
                                  "type": "integer"
                                }
                              }
                            }
                          },
                          "public_port": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "The public port routed to this service; null when it is not exposed."
                          },
                          "external_url": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "examples": [
                              "http://203.0.113.10:8088"
                            ]
                          },
                          "created_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "pods": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "name",
                          "namespace",
                          "status",
                          "ready",
                          "restarts",
                          "node_name",
                          "pod_ip",
                          "age",
                          "created_at"
                        ],
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "namespace": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "examples": [
                              "Running",
                              "Pending"
                            ]
                          },
                          "ready": {
                            "type": "string",
                            "description": "Ready containers over all containers.",
                            "examples": [
                              "1/1"
                            ]
                          },
                          "restarts": {
                            "type": "integer"
                          },
                          "node_name": {
                            "type": "string"
                          },
                          "pod_ip": {
                            "type": "string"
                          },
                          "age": {
                            "type": "string",
                            "description": "As kubectl's AGE column.",
                            "examples": [
                              "3h"
                            ]
                          },
                          "created_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`KUBERNETES_API_UNREACHABLE`: retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/apply-manifest": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Apply a manifest to a cluster",
        "description": "Applies a YAML manifest (one or more documents, up to 512 KB and 100 objects) to the cluster with server-side apply, as `kubectl apply --server-side --force-conflicts` would, in order. Namespaced objects without a namespace go in `namespace` (default `default`). Applying the same manifest again changes nothing, so a retry is safe. If the cluster refuses an object, the objects before it stay applied and the error names the one it refused.\n\nErrors: `422 VALIDATION_FAILED` with `errors[].field = manifest` and code `INVALID_KUBERNETES_MANIFEST`, whose `message` is the cluster's own reason (for example a missing field); `404 KUBERNETES_CLUSTER_NOT_FOUND`; `409 KUBERNETES_CLUSTER_NOT_RUNNING`; `503 KUBERNETES_API_UNREACHABLE` (retry).",
        "operationId": "applyKubernetesManifest",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "manifest"
                ],
                "properties": {
                  "manifest": {
                    "type": "string",
                    "maxLength": 524288
                  },
                  "namespace": {
                    "type": "string",
                    "description": "Where namespaced objects without one go; default `default`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What was applied.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "applied",
                    "cluster_id",
                    "output",
                    "resources"
                  ],
                  "properties": {
                    "applied": {
                      "type": "boolean"
                    },
                    "cluster_id": {
                      "type": "string"
                    },
                    "output": {
                      "type": "string",
                      "description": "One line per object, as kubectl prints it.",
                      "examples": [
                        "deployment.apps/web created"
                      ]
                    },
                    "resources": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "kind",
                          "name",
                          "namespace",
                          "status"
                        ],
                        "properties": {
                          "kind": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "namespace": {
                            "type": "string",
                            "description": "Empty for a cluster-wide object."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "created",
                              "configured",
                              "unchanged"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: `INVALID_KUBERNETES_MANIFEST` on `manifest`, or `REQUIRED`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`KUBERNETES_API_UNREACHABLE`: retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/live-manifests": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Export a cluster's workloads as YAML",
        "description": "Your objects as they run in the cluster now, as one multi-document YAML stream you can edit and apply back: Namespaces, ConfigMaps, Services, Deployments, StatefulSets, DaemonSets, CronJobs and Ingresses outside the `kube-*` namespaces. Fields the cluster fills in (status, resource versions, cluster IPs) are left out. Objects a controller made (a Deployment's ReplicaSets and pods) are left out, since their owner is exported. Secrets are never exported.\n\nErrors: `404 KUBERNETES_CLUSTER_NOT_FOUND`; `409 KUBERNETES_CLUSTER_NOT_RUNNING`; `503 KUBERNETES_API_UNREACHABLE` (retry).",
        "operationId": "getKubernetesLiveManifests",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The exported objects.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "cluster_id",
                    "manifest",
                    "resource_count",
                    "retrieved_at"
                  ],
                  "properties": {
                    "cluster_id": {
                      "type": "string"
                    },
                    "manifest": {
                      "type": "string",
                      "description": "Empty when you have deployed nothing."
                    },
                    "resource_count": {
                      "type": "integer"
                    },
                    "retrieved_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`KUBERNETES_CLUSTER_NOT_RUNNING`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`KUBERNETES_API_UNREACHABLE`: retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/expose-service": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Expose a Kubernetes service",
        "description": "Routes `public_port` on the cluster's public address to a Service. The Service's port becomes a NodePort (`node_port`, or the one it has, or one the cluster picks), the Service records the public port in its `pantechdynamics.com/public-port` annotation, and routing is synced. The cluster is the record of what is exposed: removing the annotation with kubectl and syncing routing takes the route away. Your subnet's firewall rules must allow the public port.\n\nPublic routing needs a cluster in a VPC subnet: it uses the VPC's public address. Port 22 and the cluster's API port are reserved.\n\nErrors: `404 KUBERNETES_CLUSTER_NOT_FOUND`; `404 KUBERNETES_SERVICE_NOT_FOUND` (apply the Service first); `409 PORT_IN_USE` (another service, cluster or resource uses that public port; choose another); `409 KUBERNETES_ROUTING_UNAVAILABLE` (a cluster with no VPC address); `409 KUBERNETES_CLUSTER_NOT_RUNNING`; `422 VALIDATION_FAILED` (`service_name`, `public_port` or `node_port`; or `INVALID_KUBERNETES_MANIFEST` when the cluster refused the change); `503 KUBERNETES_API_UNREACHABLE` (retry).",
        "operationId": "exposeKubernetesService",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "service_name",
                  "public_port"
                ],
                "properties": {
                  "service_name": {
                    "type": "string"
                  },
                  "namespace": {
                    "type": "string",
                    "description": "Default `default`."
                  },
                  "public_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535
                  },
                  "node_port": {
                    "type": "integer",
                    "minimum": 30000,
                    "maximum": 32767,
                    "description": "Leave out to keep the Service's own NodePort, or let the cluster choose one."
                  },
                  "protocol": {
                    "type": "string",
                    "enum": [
                      "TCP",
                      "UDP"
                    ],
                    "default": "TCP"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The service is routed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "cluster_id",
                    "service_name",
                    "namespace",
                    "public_ip",
                    "public_port",
                    "node_port",
                    "protocol",
                    "external_url",
                    "status"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "cluster_id": {
                      "type": "string"
                    },
                    "service_name": {
                      "type": "string"
                    },
                    "namespace": {
                      "type": "string"
                    },
                    "public_ip": {
                      "type": "string"
                    },
                    "public_port": {
                      "type": "integer"
                    },
                    "node_port": {
                      "type": "integer"
                    },
                    "protocol": {
                      "type": "string"
                    },
                    "external_url": {
                      "type": "string",
                      "examples": [
                        "http://203.0.113.10:8088"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND` or `KUBERNETES_SERVICE_NOT_FOUND`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PORT_IN_USE`, `KUBERNETES_ROUTING_UNAVAILABLE` or `KUBERNETES_CLUSTER_NOT_RUNNING`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`KUBERNETES_API_UNREACHABLE`: retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/sync-routing": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Sync a cluster's public routing",
        "description": "Reconciles the port forwards on the cluster's public address with what the cluster exposes now: its API server (unless its endpoint is private), on the cluster's own API port, and every Service carrying the `pantechdynamics.com/public-port` annotation. Routes to services no longer exposed are removed. Only the cluster's own routes are ever changed: other clusters and your own port forwards on the same address are left alone.\n\nEvery cluster on a shared address gets its own API port: the first 6443, the next 6444, and so on. A new cluster's API port is routed automatically once it is running; call this after exposing or unexposing services with kubectl. If the API server does not answer, only its own route is ensured and no service route is removed.\n\nErrors: `404 KUBERNETES_CLUSTER_NOT_FOUND`; `409 PORT_IN_USE`; `409 KUBERNETES_ROUTING_UNAVAILABLE` (a cluster with no VPC address); `409 KUBERNETES_CLUSTER_NOT_RUNNING`.",
        "operationId": "syncKubernetesRouting",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The routes now in place.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "cluster_id",
                    "public_ip",
                    "api_port",
                    "synced_ports",
                    "message"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "cluster_id": {
                      "type": "string"
                    },
                    "public_ip": {
                      "type": "string"
                    },
                    "api_port": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Null for a private endpoint."
                    },
                    "synced_ports": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "purpose",
                          "public_port",
                          "private_port",
                          "protocol",
                          "target",
                          "status"
                        ],
                        "properties": {
                          "purpose": {
                            "type": "string",
                            "enum": [
                              "kubernetes-api",
                              "service"
                            ]
                          },
                          "public_port": {
                            "type": "integer"
                          },
                          "private_port": {
                            "type": "integer"
                          },
                          "protocol": {
                            "type": "string"
                          },
                          "target": {
                            "type": "string",
                            "description": "`control node`, or the service as namespace/name."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active"
                            ]
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`KUBERNETES_CLUSTER_NOT_FOUND`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`PORT_IN_USE`, `KUBERNETES_ROUTING_UNAVAILABLE` or `KUBERNETES_CLUSTER_NOT_RUNNING`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/node-pools": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "List node pools",
        "description": "Lists the cluster's node pools.",
        "operationId": "listKubernetesNodePools",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node pools.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KubernetesNodePoolList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Create a node pool",
        "description": "Adds a node pool: workers of their own plan, joined with the pool's labels, the label `pantech.io/node-pool=<name>` and the pool's taints, so workloads choose it with a nodeSelector and tolerations. Each worker is billed as a VM of the pool's plan once it has joined (`observed_workers`). With autoscaling on, the platform adds a worker when a pod the pool could run is waiting for room, and removes the newest one after 10 idle minutes. A pool's name is unique in its cluster: sending the same pool again is answered as a replay, another pool under a taken name is `409 NODE_POOL_NAME_TAKEN`. In a zone with one fixed node size (af-abj-2), the plan must be that size (`422 KUBERNETES_PLAN_NOT_IN_ZONE`).",
        "operationId": "createKubernetesNodePool",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKubernetesNodePoolRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Cluster busy or duplicate node pool name.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/node-pools/{pool_id}": {
      "patch": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Scale a node pool",
        "description": "Changes a node pool's worker count and autoscaling. The body is the pool's whole size.",
        "operationId": "scaleKubernetesNodePool",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pool_id",
            "in": "path",
            "required": true,
            "description": "The node pool's id (`k8spool_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScaleKubernetesNodePoolRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster or node pool not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Cluster busy.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Delete a node pool",
        "description": "Removes a node pool: its workers leave the cluster (their pods move to other nodes that can run them) and are destroyed, then the pool goes. **Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteKubernetesNodePool",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pool_id",
            "in": "path",
            "required": true,
            "description": "The node pool's id (`k8spool_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster or node pool not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Cluster busy.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/addons": {
      "get": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "List cluster add-ons",
        "description": "Lists the cluster's managed add-ons and what the cluster runs of each: `status` is `active`, `installing`, `removing`, `disabled` or `unavailable`. `metrics-server` gives `kubectl top` and the Horizontal Pod Autoscaler; `csi-driver` is persistent volumes on the node's own disk (StorageClass `local-path`; the data stays on that node); `ingress-controller` is ingress-nginx, the default IngressClass, served on 80 and 443 of the cluster's public address in a VPC zone. A cluster starts with metrics-server and csi-driver on.",
        "operationId": "listKubernetesAddons",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The cluster add-ons.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KubernetesClusterAddonList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/addons/{addon_name}/toggle": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Toggle a cluster add-on",
        "description": "Turns a managed add-on on or off: `metrics-server`, `csi-driver` or `ingress-controller`. The platform applies it within moments and keeps it that way (a change made with kubectl is put back); the add-on's `status` shows when it has taken effect. Asking for the state it is already in changes nothing (empty `operation_id`).",
        "operationId": "toggleKubernetesAddon",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "addon_name",
            "in": "path",
            "required": true,
            "description": "The add-on: `metrics-server`, `csi-driver` or `ingress-controller`. Any other name is `422 INVALID_CLUSTER_ADDON`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToggleKubernetesAddonRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster or add-on not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Cluster busy.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/kubernetes-clusters/{cluster_id}/endpoint-access": {
      "post": {
        "tags": [
          "Kubernetes"
        ],
        "summary": "Configure API server endpoint access",
        "description": "Updates the cluster API endpoint access mode (`public`, `private`, or `dual`) and authorized CIDRs.",
        "operationId": "configureKubernetesEndpointAccess",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "parameters": [
          {
            "name": "cluster_id",
            "in": "path",
            "required": true,
            "description": "The cluster's id (`k8s_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfigureKubernetesEndpointAccessRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Cluster not found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Cluster busy.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Service unavailable.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/security-groups": {
      "get": {
        "tags": [
          "Security groups"
        ],
        "summary": "List security groups",
        "description": "Your security groups, newest first, with their rules. Filter by name with `q`, or by state.\n\n**Scope:** `read`.",
        "operationId": "listSecurityGroups",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 55,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of security groups.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecurityGroupList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Security groups"
        ],
        "summary": "Create a security group",
        "description": "Creates a reusable firewall for standard instances in a security-group zone (`af-abj-1`). Each rule has a `direction`, a `protocol` (`tcp`, `udp`, `icmp` or `all`), a `port_range` for `tcp`/`udp` and one IPv4 `cidr`. Inbound traffic no rule allows is dropped. A group needs at least one rule.\n\nThe name is unique among your live security groups; a deleted group frees its name. Attach the group to an instance at create (`security_group_id`) or with *Change an instance's security group*, or to a database as a source of allowed address ranges.\n\nPrefer narrow sources: a rule from `0.0.0.0/0` stops an instance from attaching a private database network interface.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The group's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createSecurityGroup",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 56,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSecurityGroupRequest"
              },
              "examples": {
                "web": {
                  "summary": "HTTPS from anywhere, SSH from one office address",
                  "value": {
                    "name": "web",
                    "rules": [
                      {
                        "direction": "ingress",
                        "protocol": "tcp",
                        "port_range": "443",
                        "cidr": "0.0.0.0/0"
                      },
                      {
                        "direction": "ingress",
                        "protocol": "tcp",
                        "port_range": "22",
                        "cidr": "203.0.113.4/32"
                      }
                    ]
                  }
                },
                "private_network_safe": {
                  "summary": "Compatible with a private database network interface: no rule overlaps 10.250.0.0/20",
                  "value": {
                    "name": "app",
                    "rules": [
                      {
                        "direction": "ingress",
                        "protocol": "tcp",
                        "port_range": "443",
                        "cidr": "203.0.113.0/24"
                      },
                      {
                        "direction": "ingress",
                        "protocol": "icmp",
                        "cidr": "198.51.100.0/24"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted; the new group's id is resource_id",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "sg_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`SECURITY_GROUP_NAME_TAKEN`: you already have a security group with this name. Choose a different name.\n`SECURITY_GROUPS_NOT_SUPPORTED_IN_ZONE`: this zone uses VPC firewall rules, not security groups.\n`PROVIDER_ACCOUNT_NOT_READY`: your organization's cloud account is still being set up, which takes a few minutes after sign-up. Retry shortly.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: the rule list is empty, or a rule has an unknown `direction` or `protocol` or an invalid IPv4 `cidr`. Send at least one valid rule.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/security-groups/{security_group_id}": {
      "get": {
        "tags": [
          "Security groups"
        ],
        "summary": "Get a security group",
        "description": "One security group and its rules.\n\n**Scope:** `read`.",
        "operationId": "getSecurityGroup",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 57,
        "parameters": [
          {
            "name": "security_group_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The security group.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecurityGroup"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no security group with this id in your organization, or the id is not a security group id (`sg_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Security groups"
        ],
        "summary": "Delete a security group",
        "description": "Deletes a security group. It must not be used by any instance. The organization's default group cannot be deleted. A group attached to a database cannot be deleted either: detach it with `PUT /public/v1/databases/{database_id}/security-groups` first.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteSecurityGroup",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 59,
        "parameters": [
          {
            "name": "security_group_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no security group with this id in your organization, or the id is not a security group id (`sg_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`DEFAULT_SECURITY_GROUP_UNDELETABLE`: the organization's default group cannot be deleted. You can change its rules instead.\n`SECURITY_GROUP_ATTACHED_TO_DATABASE`: a database uses this group; `detail` names it. Detach the group from that database, then retry.\n`INVALID_RESOURCE_STATE`: instances still use this group, or it is already being deleted. Move those instances to another group first.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/security-groups/{security_group_id}/rules": {
      "put": {
        "tags": [
          "Security groups"
        ],
        "summary": "Replace a security group's rules",
        "description": "Replaces the group's complete rule list, for every instance using it. Each rule has a `direction`, a `protocol` (`tcp`, `udp`, `icmp` or `all`), a `port_range` for `tcp`/`udp` and one IPv4 `cidr`. Inbound traffic no rule allows is dropped. A group needs at least one rule.\n\nDatabases the group is attached to are updated automatically; a list that would give one of them more than 1024 address ranges is refused. While an instance using the group has a private database network interface, an ingress rule whose source overlaps the private network's range (`10.250.0.0/20`), `0.0.0.0/0` included, is refused.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "replaceSecurityGroupRules",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 58,
        "parameters": [
          {
            "name": "security_group_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceSecurityGroupRulesRequest"
              },
              "examples": {
                "narrowed": {
                  "summary": "Replace 0.0.0.0/0 with the ranges you need",
                  "value": {
                    "rules": [
                      {
                        "direction": "ingress",
                        "protocol": "tcp",
                        "port_range": "22",
                        "cidr": "203.0.113.4/32"
                      },
                      {
                        "direction": "ingress",
                        "protocol": "tcp",
                        "port_range": "5432",
                        "cidr": "10.0.1.0/24"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                },
                "examples": {
                  "accepted": {
                    "summary": "Accepted",
                    "value": {
                      "operation_id": "op_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "resource_id": "sg_06gk3x9tq7m2v8r4y1c5d0zp8w",
                      "status": "submitting"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no security group with this id in your organization, or the id is not a security group id (`sg_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the security group cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`rules` `REQUIRED`: send the complete rule list.\n`rules` `RULE_ALLOWS_PRIVATE_NETWORK`: an instance using this group has a private database network interface, and a rule's source overlaps the private network's range; the message names the range and the rules. Replace `0.0.0.0/0` (and any other overlapping source) with narrower ranges that leave out `10.250.0.0/20`.\n`rules` `DATABASE_ACCESS_RANGE_LIMIT_EXCEEDED`: a database this group is attached to would get more than 1024 address ranges. Use fewer or wider (but at most /8) ranges, or detach the group from that database.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: the list is empty, or a rule has an unknown `direction` or `protocol` or an invalid IPv4 `cidr`. Send at least one valid rule.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/snapshots": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "List snapshots",
        "description": "Every snapshot in your organization: of instances' root disks, of volumes, and of databases' data disks. `instance_id`, `volume_id` or `database_id` says which.\n\n**Scope:** `read`.",
        "operationId": "listSnapshots",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 72,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of snapshots.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/snapshots/quote": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Price a snapshot",
        "description": "What a snapshot of `size_gb` GB costs per month, in your organization's currency. A snapshot is billed on its physical size.\n\n**Scope:** `read`.",
        "operationId": "quoteSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 73,
        "parameters": [
          {
            "name": "size_gb",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The price.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OptionalQuote"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: cost quotes are not available on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`size_gb` `INVALID_SIZE`: send a whole number of GB, at least 1.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/snapshots/{snapshot_id}": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Get a snapshot",
        "description": "One snapshot.\n\n**Scope:** `read`.",
        "operationId": "getSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 74,
        "parameters": [
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The snapshot.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no snapshot with this id in your organization, or the id is not a snapshot id (`snap_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Delete a snapshot",
        "description": "Deletes a snapshot of an instance, volume or database. It is billed until the deletion completes.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 75,
        "parameters": [
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no snapshot with this id in your organization, or the id is not a snapshot id (`snap_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the snapshot cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/snapshots/{snapshot_id}/restore": {
      "post": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Restore a snapshot to a new volume",
        "description": "Creates a new volume from an instance or volume snapshot, of `disk_offering_slug` and at least the snapshot's size. A database snapshot cannot be restored yet. To roll an instance's root disk back to its snapshot instead, use *Restore an instance from a snapshot*.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The new volume's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "restoreSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 76,
        "parameters": [
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreSnapshotRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no snapshot with this id in your organization, or the id is not a snapshot id (`snap_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the snapshot cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` or `disk_offering_slug` `REQUIRED`: send both.\n`disk_offering_slug` `DISK_OFFERING_NOT_FOUND`: no active disk offering has this slug. Pick one from `GET /public/v1/disk-offerings`.\n`size_gb` `SIZE_REQUIRED`: a custom-size offering needs `size_gb`, at least the snapshot's size.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/snapshots/{snapshot_id}/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get a snapshot's usage",
        "description": "Measured storage usage for this snapshot in the current billing period.\n\n**Scope:** `read`.",
        "operationId": "getSnapshotUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 77,
        "parameters": [
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no snapshot with this id in your organization, or the id is not a snapshot id (`snap_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/ssh-keys": {
      "get": {
        "tags": [
          "SSH keys"
        ],
        "summary": "List SSH keys",
        "description": "The SSH keys you can install on new instances.\n\n**Scope:** `read`.",
        "operationId": "listSSHKeys",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 78,
        "responses": {
          "200": {
            "description": "SSH keys.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SSHKeyList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "SSH keys"
        ],
        "summary": "Add or generate an SSH key",
        "description": "Send `public_key` to register your own OpenSSH public key. Leave it out to have a key pair generated: the private key is returned in this response only and never stored. Returns `201` at once; there is no operation to follow.\n\n**Idempotency:** a retry with the same `Idempotency-Key` is not replayed yet. If a request may have gone through, list your SSH keys before retrying: a second attempt with the same name returns `409 SSH_KEY_NAME_TAKEN`, and a generated private key is never shown again.\n\n**Scope:** `write`.",
        "operationId": "createSSHKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 79,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSSHKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The key. `private_key` is present only for a generated key.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeneratedSSHKey"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`SSH_KEY_NAME_TAKEN`: you already have an SSH key with this name. Choose a different name.\n`SSH_KEY_ALREADY_EXISTS`: this public key is already registered. Use the existing key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `INVALID_NAME`: send a name of 1 to 255 characters.\n`public_key` `INVALID_SSH_PUBLIC_KEY`: send one OpenSSH public key line, such as `ssh-ed25519 AAAA… comment`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/ssh-keys/{ssh_key_id}": {
      "get": {
        "tags": [
          "SSH keys"
        ],
        "summary": "Get an SSH key",
        "description": "One SSH key.\n\n**Scope:** `read`.",
        "operationId": "getSSHKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 80,
        "parameters": [
          {
            "name": "ssh_key_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The key.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SSHKey"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no SSH key with this id in your organization, or the id is not a SSH key id (`sshk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "SSH keys"
        ],
        "summary": "Delete an SSH key",
        "description": "Deletes an SSH key. Instances that already have it keep it in their `authorized_keys`; remove it there yourself.\n\n**Idempotency:** a retry is not replayed. Once the key is deleted, a repeat returns `404`; treat that as done.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteSSHKey",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 81,
        "parameters": [
          {
            "name": "ssh_key_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no SSH key with this id in your organization, or the id is not a SSH key id (`sshk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/subnets/{subnet_id}": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "Get a subnet",
        "description": "One subnet, with the number of instances in it.\n\n**Scope:** `read`.",
        "operationId": "getSubnet",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 40,
        "parameters": [
          {
            "name": "subnet_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The subnet.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subnet"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no subnet with this id in your organization, or the id is not a subnet id (`snet_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Networks"
        ],
        "summary": "Delete a subnet",
        "description": "Deletes a subnet. It must hold no instances or databases.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteSubnet",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 41,
        "parameters": [
          {
            "name": "subnet_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no subnet with this id in your organization, or the id is not a subnet id (`snet_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the subnet still has instances or databases, or is already being deleted. Delete them first.\n`SUBNET_HAS_KUBERNETES_CLUSTERS`: Kubernetes clusters still run in this subnet. Delete them first.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused a value, for example a malformed CIDR or a name longer than 255 characters. Check the request against this page.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/subnets/{subnet_id}/firewall-rules": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "List a subnet's firewall rules",
        "description": "The subnet's firewall rules, in evaluation order, and the platform's fixed rules around them (`system_rules`), which always apply.\n\n**Scope:** `read`.",
        "operationId": "listFirewallRules",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 42,
        "parameters": [
          {
            "name": "subnet_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rules.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirewallRuleList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no subnet with this id in your organization, or the id is not a subnet id (`snet_…`). Check the id.\n`NOT_FOUND`: firewall rules are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`FIREWALL_RULES_NOT_SUPPORTED`: firewall rules apply to VPC subnets only. Standard instances use security groups.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Networks"
        ],
        "summary": "Add a firewall rule",
        "description": "Adds a rule to the subnet's firewall. Rules are evaluated by `number`, lowest first, and the first match decides; traffic no rule allows is dropped. A rule applies to the whole subnet. Defaults: `direction` `ingress`, `action` `allow`, `port_end` equal to `port_start`.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The rule's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createFirewallRule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 43,
        "parameters": [
          {
            "name": "subnet_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFirewallRuleRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no subnet with this id in your organization, or the id is not a subnet id (`snet_…`). Check the id.\n`NOT_FOUND`: firewall rules are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`FIREWALL_RULES_NOT_SUPPORTED`: firewall rules apply to VPC subnets only. Standard instances use security groups.\n`INVALID_RESOURCE_STATE`: the subnet cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`protocol` or `cidr` `REQUIRED`: send both.\n`number` `INVALID_RULE_NUMBER`: use 100 to 9999.\n`number` `RULE_NUMBER_TAKEN`: another rule on this subnet has this number. Choose another.\n`port_start` `INVALID_PORTS`: send ports 1 to 65535 for `tcp` or `udp`, and leave them out for `icmp` or `all`.\n`protocol` `INVALID_FIREWALL_RULE`: `direction`, `protocol`, `action` or the ICMP fields are not valid values.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/subnets/{subnet_id}/firewall-rules/{rule_id}": {
      "get": {
        "tags": [
          "Networks"
        ],
        "summary": "Get a firewall rule",
        "description": "One firewall rule on the subnet.\n\n**Scope:** `read`.",
        "operationId": "getFirewallRule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 44,
        "parameters": [
          {
            "name": "subnet_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "description": "The rule's id (`aclr_...` for a firewall rule, `pfr_...` for a port forwarding rule).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rule.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirewallRule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no rule with this id on this subnet, or no such subnet in your organization. Check both ids.\n`NOT_FOUND`: firewall rules are not offered on this platform yet.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`FIREWALL_RULES_NOT_SUPPORTED`: firewall rules apply to VPC subnets only. Standard instances use security groups.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get usage",
        "description": "Measured usage for the whole organization in the current billing period.\n\n**Scope:** `read`.",
        "operationId": "getUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 84,
        "responses": {
          "200": {
            "description": "Usage.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/usage/by-resource": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get cost by resource",
        "description": "What each resource cost over `period`: the last `30d` or `7d`, this `month` or `last_month`.\n\n**Scope:** `read`.",
        "operationId": "getUsageByResource",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 85,
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "30d",
                "7d",
                "month",
                "last_month"
              ],
              "default": "30d"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cost per resource.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageByResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`period` `INVALID_PERIOD`: use `30d`, `7d`, `month` or `last_month`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`BILLING_UNAVAILABLE`: billing is not answering right now. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes": {
      "get": {
        "tags": [
          "Volumes"
        ],
        "summary": "List volumes",
        "description": "Your volumes, newest first, with what each costs per month. Filter by name with `q`, or by state.\n\n**Scope:** `read`.",
        "operationId": "listVolumes",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 60,
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of volumes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VolumeList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Volumes"
        ],
        "summary": "Create a volume",
        "description": "Creates a data disk of `disk_offering_slug` (see `GET /public/v1/disk-offerings`; send `size_gb` for a custom-size offering). Send `instance_id` to attach it at once to a running instance in the same zone, and `mount_point` to have it mounted there.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The volume's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createVolume",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 61,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVolumeRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`PROVIDER_ACCOUNT_NOT_READY`: your organization's cloud account is still being set up, which takes a few minutes after sign-up. Retry shortly.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` or `disk_offering_slug` `REQUIRED`: send both.\n`name` `NAME_TOO_LONG`: at most 255 characters.\n`disk_offering_slug` `DISK_OFFERING_NOT_FOUND`: no active disk offering has this slug. Pick one from `GET /public/v1/disk-offerings`.\n`size_gb` `SIZE_REQUIRED`: a custom-size offering needs `size_gb`.\n`instance_id` `INSTANCE_NOT_FOUND`: not one of your instances.\n`instance_id` `INSTANCE_NOT_RUNNING`: the instance must be running to attach a volume at create. Start it, or attach the volume later.\n`instance_id` `INSTANCE_WRONG_ZONE`: the instance is in another zone than the volume.\n`mount_point` `INVALID_MOUNT_POINT`: send an absolute path such as `/data`.\n`region` `REGION_NOT_AVAILABLE`: pick a region from `GET /public/v1/regions`.\n`encrypted` `ENCRYPTION_NOT_SUPPORTED`: encrypted volumes are not enabled for your organization yet. Create a plain volume, or send `encrypted` as `false`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`ENCRYPTED_VOLUMES_UNAVAILABLE`: you asked for an encrypted volume but the encrypted volume service is not available right now. Retry later, or create a plain volume.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}": {
      "get": {
        "tags": [
          "Volumes"
        ],
        "summary": "Get a volume",
        "description": "One volume, with where it is attached and what it costs.\n\n**Scope:** `read`.",
        "operationId": "getVolume",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 62,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The volume.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Volume"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Volumes"
        ],
        "summary": "Delete a volume",
        "description": "Deletes a volume and its data. Detach it first. Its snapshots are kept and stay billed until you delete them.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteVolume",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 63,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the volume is still attached, or is already being deleted. Detach it first.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused a value, for example a malformed CIDR or a name longer than 255 characters. Check the request against this page.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}/attach": {
      "post": {
        "tags": [
          "Volumes"
        ],
        "summary": "Attach a volume",
        "description": "Attaches a detached volume to a running instance in the same zone. Mount it inside the instance afterwards.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "attachVolume",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 64,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachVolumeRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the volume is already attached or changing, or the instance is not running. Detach it first, or start the instance.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`instance_id` `REQUIRED` or `INSTANCE_NOT_FOUND`: send one of your instances.\n`instance_id` `INSTANCE_NOT_RUNNING`: the instance must be running.\n`instance_id` `INSTANCE_WRONG_ZONE`: the instance is in another zone than the volume. Volumes attach only within their zone.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}/detach": {
      "post": {
        "tags": [
          "Volumes"
        ],
        "summary": "Detach a volume",
        "description": "Detaches a volume from its instance. Unmount it inside the instance first, or data being written may be lost.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "detachVolume",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 65,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`INVALID_RESOURCE_STATE`: the volume is not attached, or is changing. Wait for its current operation to finish.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED` with no `errors` entry: the platform refused the request, for example because the resource has already been deleted. Read the resource to check its state.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}/resize": {
      "post": {
        "tags": [
          "Volumes"
        ],
        "summary": "Grow a volume",
        "description": "Grows a volume to a bigger offering, or to a bigger `size_gb` of a custom-size offering. Volumes only grow. Extend the file system from inside the instance afterwards. No upfront charge: the larger size is billed hourly.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "resizeVolume",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 66,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResizeVolumeRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the new size is not larger than the current one, or the volume is changing. Send a larger size, or wait.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`disk_offering_slug` `REQUIRED` or `DISK_OFFERING_NOT_FOUND`: send an active offering's slug.\n`size_gb` `SIZE_REQUIRED`: a custom-size offering needs `size_gb`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}/snapshot-schedule": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Get a volume's snapshot schedule",
        "description": "The volume's automatic snapshot schedule: how often a snapshot of its volume is taken, how many are kept, and when the next one runs.\n\n**Scope:** `read`.",
        "operationId": "getVolumeSnapshotSchedule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 70,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The schedule.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotSchedule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.\n`SNAPSHOT_SCHEDULE_NOT_FOUND`: no schedule has been set for this resource. Set one with the `PUT` on this path.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "put": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Set a volume's snapshot schedule",
        "description": "Turns automatic snapshots of the volume on, changes them, or pauses them with `enabled: false`. `frequency` is `daily`, `weekly` or `monthly`; `retention_count` (1 to 168, default 7) successful snapshots are kept and older automatic ones are deleted. Automatic snapshots are billed like manual ones.\n\nReturns the schedule at once (`200`); no operation to follow. Send an `Idempotency-Key`: a retry with the same key and settings returns the same schedule.\n\n**Scope:** `write`. Lowering `retention_count` deletes the oldest copies, so an AI app's key also needs `delete` for that (`403 INSUFFICIENT_SCOPE` otherwise).",
        "operationId": "putVolumeSnapshotSchedule",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 71,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutSnapshotScheduleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The schedule.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotSchedule"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`IDEMPOTENCY_CONFLICT`: this `Idempotency-Key` was already used with different settings. Use a new key for a different request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`frequency` `REQUIRED`: send `daily`, `weekly` or `monthly`.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.\n`VALIDATION_FAILED` with no `errors` entry: `frequency` is not `daily`, `weekly` or `monthly`, or `retention_count` is outside 1 to 168.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}/snapshots": {
      "get": {
        "tags": [
          "Snapshots"
        ],
        "summary": "List a volume's snapshots",
        "description": "Snapshots of this volume, oldest first.\n\n**Scope:** `read`.",
        "operationId": "listVolumeSnapshots",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 68,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Q"
          },
          {
            "$ref": "#/components/parameters/DesiredState"
          },
          {
            "$ref": "#/components/parameters/ObservedState"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of snapshots.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not a whole number from 1 to 100. Send a value in that range, or leave it out for 50.\n`INVALID_CURSOR`: `cursor` does not belong to this list with these filters. Start again without a cursor.\n`INVALID_FILTER`: `q` is longer than 255 characters, or `desired_state` or `observed_state` is not one of its listed values. Fix the parameter named in `detail`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Snapshots"
        ],
        "summary": "Snapshot a volume",
        "description": "Takes a snapshot of the volume, named `name`. A snapshot of an attached volume is crash-consistent. Billed on its physical size, hourly, until deleted.\n\nReturns `202 Accepted` with an `operation_id` (also in the `Location` header). The change happens in the background: poll `GET /public/v1/operations/{operation_id}`, or stream `/events`, until `status` is `succeeded` or `failed`; a failed operation carries a stable `failure.code` and a readable `failure.reason`. The new snapshot's id is the operation's `resource_id`.\n\nSend an `Idempotency-Key`. A retry with the same key returns the original operation instead of making the change twice.\n\n**Scope:** `write`.",
        "operationId": "createVolumeSnapshot",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 69,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSnapshotRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Follow `operation_id` until it finishes.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`SNAPSHOT_NAME_TAKEN`: this volume already has a snapshot with that name. Choose a different name.\n`ACCOUNT_SUSPENDED`: an invoice is overdue, or the organization was suspended for non-payment. Pay the outstanding invoice in the console, then retry.\n`INVALID_RESOURCE_STATE`: the volume cannot do this in its current state, for example while it is being created or deleted. Wait for its current operation to finish, then retry.\n`CONCURRENT_UPDATE`: the resource changed while this request was being processed. Retry the request; if it repeats, read the resource first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`name` `REQUIRED` or `NAME_TOO_LONG`: send a name of 1 to 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.\n`PROVISIONING_UNAVAILABLE`: the provisioning service is temporarily unavailable. Wait a few seconds, then retry with the same `Idempotency-Key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/volumes/{volume_id}/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get a volume's usage",
        "description": "Measured storage usage for this volume in the current billing period.\n\n**Scope:** `read`.",
        "operationId": "getVolumeUsage",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 67,
        "parameters": [
          {
            "name": "volume_id",
            "in": "path",
            "required": true,
            "description": "The resource's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RESOURCE_NOT_FOUND`: no volume with this id in your organization, or the id is not a volume id (`vol_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/QuotaUnavailable"
          }
        }
      }
    },
    "/public/v1/webhook-event-types": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook event types",
        "description": "Every event type a webhook can subscribe to, with what it means. Subscribe to an exact type, to every type of one resource with `<resource>.*` (for example `instance.*`), or to everything with `*`.\n\nInfrastructure events are named `<resource>.<past tense>` when a change finished (`instance.created`, `volume.attached`) and `<resource>.<verb>_failed` when it failed (`instance.create_failed`).\n\n**Scope:** `read`.",
        "operationId": "listWebhookEventTypes",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 125,
        "responses": {
          "200": {
            "description": "Event types.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEventTypeList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Your organization's webhooks: the URLs Pantech sends events to. The signing secret is never part of a webhook; it is shown once, when the webhook is created and when its secret is rotated.\n\n**Scope:** `read`.",
        "operationId": "listWebhooks",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 126,
        "responses": {
          "200": {
            "description": "Webhooks.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook",
        "description": "Adds a URL Pantech sends events to. Every delivery is a JSON `POST` signed with the webhook's secret, which is in this response only: store it now.\n\n**Verifying a delivery.** Each request carries `Pantech-Signature: t=<unix seconds>,v1=<hex>`. Compute HMAC-SHA256 of `<t>.<raw body>` with the secret and compare it, in constant time, with any `v1` value; reject a `t` more than five minutes old. During the 24 hours after a rotation there are two `v1` values, one per secret. `Pantech-Event-Id`, `Pantech-Event-Type` and `Pantech-Delivery-Id` name what was sent.\n\n**Delivery.** Any `2xx` within 10 seconds is success. Anything else, including a redirect, is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours, then marked failed. A webhook that has failed for three days without a single success is disabled. Events can arrive more than once and out of order: deduplicate on the event `id`.\n\nAt most 10 webhooks per organization. Owners and admins only.\n\n**Idempotency:** a retry with the same `Idempotency-Key` returns the webhook the first request made, with `secret: null`: the secret is never shown again. The same key with a different request returns `409 IDEMPOTENCY_CONFLICT`.\n\n**Scope:** `write`.",
        "operationId": "createWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 127,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The webhook, with its `secret`, or `secret: null` on a replay.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE`: the API key lacks the `write` scope. Use a key with that scope.\n`FORBIDDEN`: the member who created the key is not an owner or admin. Use a key created by one.\n`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server. An owner can turn it on in the console under Organization › AI apps.\n`WEBHOOK_LIMIT_REACHED`: your organization already has 10 webhooks. Delete one first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`IDEMPOTENCY_CONFLICT`: this `Idempotency-Key` was already used for a different webhook. Use a new key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`url` `REQUIRED` or `INVALID_WEBHOOK_URL`: send an `https` URL on the public internet, with no user name or password, of at most 2,048 characters.\n`events` `INVALID_WEBHOOK_EVENTS`: send 1 to 100 entries, each an event type from `GET /webhook-event-types`, `<resource>.*`, or `*`.\n`description` `INVALID_DESCRIPTION`: send at most 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks/{webhook_id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a webhook",
        "description": "One webhook. `failing_since` is when its deliveries started failing without a success since; null while they succeed.\n\n**Scope:** `read`.",
        "operationId": "getWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 128,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`RESOURCE_NOT_FOUND`: the id is not a webhook id (`whk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Change a webhook",
        "description": "Changes the URL, description, events or `enabled`; fields you leave out keep their value. Enabling a disabled webhook clears its failure history. Deliveries still waiting for a disabled webhook are cancelled when they come due.\n\n**Idempotency:** the same request applied twice leaves the webhook the same.\n\n**Scope:** `write`.",
        "operationId": "updateWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 129,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed webhook.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.\n`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`RESOURCE_NOT_FOUND`: the id is not a webhook id (`whk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`CONFLICT`: the webhook was changed at the same time. Get it again and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:\n`url` `REQUIRED` or `INVALID_WEBHOOK_URL`: send an `https` URL on the public internet, with no user name or password, of at most 2,048 characters.\n`events` `INVALID_WEBHOOK_EVENTS`: send 1 to 100 entries, each an event type from `GET /webhook-event-types`, `<resource>.*`, or `*`.\n`description` `INVALID_DESCRIPTION`: send at most 255 characters.\n`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook",
        "description": "Deletes a webhook and its delivery history. Nothing more is sent to it.\n\n**Idempotency:** a retry is not replayed. Once the webhook is deleted, a repeat returns `404`; treat that as done.\n\n**Scope:** `write`. Destructive: an AI app's key also needs `delete`.",
        "operationId": "deleteWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-destructive": true,
        "x-order": 130,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`RESOURCE_NOT_FOUND`: the id is not a webhook id (`whk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks/{webhook_id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "description": "Queues a `webhook.test` event to this webhook, whatever it subscribes to, and returns the delivery. It is sent within a few seconds and retried like any other.\n\n**Idempotency:** a retry is not replayed: each request sends another test event.\n\n**Scope:** `write`.",
        "operationId": "testWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 131,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "The queued delivery.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetail"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`RESOURCE_NOT_FOUND`: the id is not a webhook id (`whk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`WEBHOOK_DISABLED`: the webhook is disabled. Enable it first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks/{webhook_id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate a webhook's secret",
        "description": "Replaces the signing secret, which is in this response only. For 24 hours every delivery is signed with both the new and the old secret, so you can update your receiver without dropping events.\n\n**Idempotency:** a retry is not replayed: each request rotates again, and only the latest secret and the one before it sign.\n\n**Scope:** `write`.",
        "operationId": "rotateWebhookSecret",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 132,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook with its new `secret`.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`RESOURCE_NOT_FOUND`: the id is not a webhook id (`whk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`CONFLICT`: the webhook was changed at the same time. Retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks/{webhook_id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List a webhook's deliveries",
        "description": "Every event sent or waiting to be sent to this webhook, newest first, kept for 30 days: its status, attempts, and how the last attempt went.\n\n**Scope:** `read`.",
        "operationId": "listWebhookDeliveries",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 133,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Deliveries.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_PAGE`: `limit` is not an integer from 1 to 100.\n`INVALID_CURSOR`: the cursor is not valid for this list. Start again without one.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`RESOURCE_NOT_FOUND`: the id is not a webhook id (`whk_…`). Check the id.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks/{webhook_id}/deliveries/{delivery_id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a delivery",
        "description": "One delivery, with `payload`: the exact body sent.\n\n**Scope:** `read`.",
        "operationId": "getWebhookDelivery",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "read",
        "x-order": 134,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "description": "The delivery's id (`whd_…`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The delivery.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`WEBHOOK_DELIVERY_NOT_FOUND`: no delivery with this id for this webhook.\n`RESOURCE_NOT_FOUND`: an id is not a webhook id (`whk_…`) or delivery id (`whd_…`). Check the ids.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/public/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/redeliver": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a delivery again",
        "description": "Queues a delivery that succeeded, failed or was cancelled to be sent again from its first attempt, with the same event `id`.\n\n**Idempotency:** a retry while it is being sent returns `409 WEBHOOK_DELIVERY_IN_PROGRESS`; treat that as done.\n\n**Scope:** `write`.",
        "operationId": "redeliverWebhook",
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scope": "write",
        "x-order": 135,
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "description": "The webhook's id (`whk_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "description": "The delivery's id (`whd_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "The queued delivery.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed per window for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in this window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "This request's id.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              }
            }
          },
          "400": {
            "description": "`IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.\n`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`WEBHOOK_NOT_FOUND`: no webhook with this id in your organization. List your webhooks to find it.\n`WEBHOOK_DELIVERY_NOT_FOUND`: no delivery with this id for this webhook.\n`RESOURCE_NOT_FOUND`: an id is not a webhook id (`whk_…`) or delivery id (`whd_…`). Check the ids.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`WEBHOOK_DISABLED`: the webhook is disabled. Enable it first.\n`WEBHOOK_DELIVERY_IN_PROGRESS`: the delivery is still being attempted. Wait for it to finish.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`WEBHOOKS_UNAVAILABLE`: webhooks are not available on this deployment yet. Try again later.\n`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key (PAN_…)",
        "description": "An API key from the console: `Authorization: Bearer PAN_…`."
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Items per page, 1 to 100. Defaults to 50.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "The previous page's `next_cursor`, to get the next page. Leave out for the first page; keep the other parameters the same.",
        "schema": {
          "type": "string"
        }
      },
      "Q": {
        "name": "q",
        "in": "query",
        "description": "Only items whose name contains this text (case-insensitive), at most 255 characters.",
        "schema": {
          "type": "string",
          "maxLength": 255
        }
      },
      "DesiredState": {
        "name": "desired_state",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "present",
            "deleted"
          ]
        },
        "description": "Only items with this `desired_state`: `present` or `deleted`."
      },
      "ObservedState": {
        "name": "observed_state",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "provisioning",
            "active",
            "deleting",
            "deleted",
            "failed",
            "unknown"
          ]
        },
        "description": "Only items with this `observed_state`."
      },
      "InstanceDesiredState": {
        "name": "desired_state",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "running",
            "stopped",
            "deleted"
          ]
        },
        "description": "Only items with this `desired_state`: `running`, `stopped` or `deleted`."
      },
      "InstanceObservedState": {
        "name": "observed_state",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "pending",
            "provisioning",
            "running",
            "stopping",
            "stopped",
            "deleting",
            "deleted",
            "failed",
            "unknown"
          ]
        },
        "description": "Only items with this `observed_state`."
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "A unique value per change, e.g. a UUID. Retrying with the same key returns the original result instead of repeating the change; reusing it for a different request is an error. Required on every POST, PUT and DELETE.",
        "schema": {
          "type": "string",
          "maxLength": 255
        }
      }
    },
    "responses": {
      "Unauthenticated": {
        "description": "`UNAUTHENTICATED`: the request has no API key, or the key is mistyped, revoked or expired, or its creator has left the organization. Send `Authorization: Bearer PAN_…` with a valid key; create one in the console under Organization › API keys.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`INSUFFICIENT_SCOPE`: the API key lacks the scope this endpoint needs (`read` for GET, `write` for changes; an AI app's key also needs `delete` for a destructive call). Use a key with that scope, or reconnect the AI app with \"Manage and delete\" access.\n`FORBIDDEN`: the member who created the key may not do this in the organization. Use a key created by an owner or admin.\n`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server (`Pantech-Client: mcp/…`). An owner can turn it on in the console under Organization › AI apps.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "QuotaUnavailable": {
        "description": "`SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`RATE_LIMITED`: this API key, verified user or organization used its request budget for the current window, or this address exceeded an IP/failed-auth limit. Wait `Retry-After` seconds, then retry. For authenticated quota denials, `RateLimit-Scope` identifies the denying quota and `RateLimit-Reset` reports its remaining window in seconds.",
        "headers": {
          "RateLimit-Scope": {
            "schema": {
              "type": "string",
              "enum": [
                "api_key",
                "user",
                "organization"
              ]
            }
          },
          "RateLimit-Limit": {
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "schema": {
              "type": "integer"
            }
          },
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "schemas": {
      "Accepted": {
        "type": "object",
        "description": "Returned with `202 Accepted` by every asynchronous write.",
        "required": [
          "operation_id",
          "resource_id",
          "status"
        ],
        "properties": {
          "operation_id": {
            "type": "string",
            "description": "The operation carrying out the change. Poll `GET /public/v1/operations/{operation_id}` (also the `Location` header) until `status` is `succeeded` or `failed`."
          },
          "resource_id": {
            "type": "string",
            "description": "The resource being created or changed, e.g. the new snapshot's id for a snapshot create."
          },
          "status": {
            "type": "string",
            "description": "The operation's status when the request was accepted, usually `submitting`. Follow `operation_id` for the outcome."
          }
        }
      },
      "AttachVolumeRequest": {
        "type": "object",
        "required": [
          "instance_id"
        ],
        "properties": {
          "instance_id": {
            "type": "string",
            "description": "A running instance in the volume's zone, e.g. `vm_…`.",
            "examples": [
              "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          }
        }
      },
      "ChangeSecurityGroupRequest": {
        "type": "object",
        "required": [
          "security_group_id"
        ],
        "properties": {
          "security_group_id": {
            "type": "string",
            "description": "One of your security groups in the instance's zone, e.g. `sg_…`. If the instance has a private database network interface, the group must allow nothing from `10.250.0.0/20`.",
            "examples": [
              "sg_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          }
        }
      },
      "CreateFirewallRuleRequest": {
        "type": "object",
        "required": [
          "number",
          "protocol",
          "cidr"
        ],
        "properties": {
          "number": {
            "type": "integer",
            "description": "Evaluation order, 100 to 9999, unique on the subnet; lower numbers are evaluated first and the first match decides.",
            "minimum": 100,
            "maximum": 9999,
            "examples": [
              100
            ]
          },
          "direction": {
            "type": "string",
            "default": "ingress",
            "description": "`ingress` (traffic into the subnet) or `egress` (traffic out of it). Defaults to `ingress`.",
            "enum": [
              "ingress",
              "egress"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "`tcp`, `udp`, `icmp` or `all`.",
            "enum": [
              "tcp",
              "udp",
              "icmp",
              "all"
            ]
          },
          "port_start": {
            "type": "integer",
            "description": "First port, 1 to 65535. For `tcp` and `udp` only; leave out for `icmp` and `all`.",
            "examples": [
              443
            ]
          },
          "port_end": {
            "type": "integer",
            "description": "Last port, 1 to 65535, at least `port_start`. Defaults to `port_start` (one port).",
            "examples": [
              443
            ]
          },
          "icmp_type": {
            "type": "integer",
            "description": "ICMP type, for `icmp` only, e.g. `8` for echo request. Leave out for every type.",
            "examples": [
              8
            ]
          },
          "icmp_code": {
            "type": "integer",
            "description": "ICMP code, for `icmp` only. Leave out for every code.",
            "examples": [
              0
            ]
          },
          "cidr": {
            "type": "string",
            "description": "One IPv4 CIDR: the source for `ingress`, the destination for `egress`. `0.0.0.0/0` means anywhere.",
            "examples": [
              "203.0.113.0/24"
            ]
          },
          "action": {
            "type": "string",
            "default": "allow",
            "description": "`allow` or `deny`. Defaults to `allow`.",
            "enum": [
              "allow",
              "deny"
            ]
          }
        }
      },
      "CreateInstanceRequest": {
        "type": "object",
        "required": [
          "name",
          "plan_slug",
          "image_slug",
          "ssh_key_id"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters of lowercase letters a-z, digits 0-9 and hyphens (-), starting and ending with a letter or digit, unique among your instances. Anything else is refused with 422 INVALID_INSTANCE_NAME. The guest hostname is derived from it (at most 63 characters).",
            "minLength": 1,
            "maxLength": 255,
            "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
            "examples": [
              "web-1"
            ]
          },
          "plan_slug": {
            "type": "string",
            "description": "The size, from `GET /public/v1/plans`.",
            "examples": [
              "starter"
            ]
          },
          "image_slug": {
            "type": "string",
            "description": "The operating system, from `GET /public/v1/images`. It must run in the instance's zone.",
            "examples": [
              "ubuntu-24-04"
            ]
          },
          "encrypted": {
            "type": "boolean",
            "description": "Optional. `true` creates the encrypted version of `image_slug`: the disk is encrypted on first boot with a key held by Pantech's key servers, and the instance needs outbound access to them at every boot (the platform keeps that open). Refused with `ENCRYPTION_NOT_SUPPORTED` when the image has no encrypted version available to your organization. `false` or omitted creates the image as named. Naming an encrypted image's own slug already creates an encrypted instance; sending `false` with that slug is refused as `ENCRYPTION_CONFLICT`.",
            "examples": [
              true
            ]
          },
          "ssh_key_id": {
            "type": "string",
            "description": "An SSH key from `GET /public/v1/ssh-keys`, installed for the default user. Required: images have no password login, so this key is how you log in.",
            "examples": [
              "sshk_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "region": {
            "type": "string",
            "description": "A region from `GET /public/v1/regions`, e.g. `af-abj`. Defaults to the platform's region.",
            "examples": [
              "af-abj"
            ]
          },
          "subnet_id": {
            "type": "string",
            "description": "Place the instance in this VPC subnet, with a private address only. Leave out for a standard instance with its own public IPv4.",
            "examples": [
              "snet_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "network_id": {
            "type": "string",
            "description": "The subnet's VPC. Optional when `subnet_id` is set; if sent, the subnet must belong to it.",
            "examples": [
              "net_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "security_group_id": {
            "type": "string",
            "description": "Standard instances only: one of your security groups. Defaults to the organization's default group, which starts with one rule: ICMP (ping) from anywhere.",
            "examples": [
              "sg_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "tags": {
            "type": "object",
            "description": "Your own labels, as string keys and values. Not interpreted by the platform.",
            "examples": [
              {
                "env": "production"
              }
            ],
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "CreateNetworkRequest": {
        "type": "object",
        "required": [
          "name",
          "cidr"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters, unique among your VPC networks.",
            "minLength": 1,
            "maxLength": 255,
            "examples": [
              "prod"
            ]
          },
          "cidr": {
            "type": "string",
            "description": "The VPC's private IPv4 range, e.g. `10.0.0.0/16`. Subnets are carved from it.",
            "examples": [
              "10.0.0.0/16"
            ]
          },
          "region": {
            "type": "string",
            "description": "A region from `GET /public/v1/regions` that offers VPC networks. Defaults to the platform's region.",
            "examples": [
              "af-abj"
            ]
          }
        }
      },
      "CreateLoadBalancerRequest": {
        "type": "object",
        "required": [
          "name",
          "public_port"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 63 characters.",
            "examples": [
              "web"
            ]
          },
          "zone_id": {
            "type": "string",
            "description": "The zone to place the load balancer in.",
            "examples": [
              "zone_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "kind": {
            "type": "string",
            "description": "`vpc_native` (a VPC zone: needs `public_ip_id` and `subnet_id`) or `appliance` (a standard zone: needs `zone_id`; a load balancer VM with its own public address, billed as that VM). Left out, it is `vpc_native` when `subnet_id` is given and `appliance` when only `zone_id` is. Anything else is `422 INVALID_LOAD_BALANCER_KIND`; an appliance in a zone that does not offer one fails its operation with `LOAD_BALANCER_APPLIANCE_UNAVAILABLE`.",
            "enum": [
              "vpc_native",
              "appliance"
            ]
          },
          "public_ip_id": {
            "type": "string",
            "description": "An active public IP with `purpose` `load_balancer` (required for `vpc_native`).",
            "examples": [
              "pip_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "subnet_id": {
            "type": "string",
            "description": "A subnet of the public IP's private network. Every target must be in it (required for `vpc_native`).",
            "examples": [
              "snet_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "algorithm": {
            "type": "string",
            "default": "roundrobin",
            "description": "`roundrobin` takes turns, `leastconn` picks the target with the fewest connections, `source` keeps a client on one target.",
            "enum": [
              "roundrobin",
              "leastconn",
              "source"
            ]
          },
          "public_port": {
            "type": "integer",
            "description": "The TCP port clients connect to, 1 to 65535.",
            "examples": [
              443
            ]
          },
          "private_port": {
            "type": "integer",
            "description": "The port on each target. Defaults to `public_port`.",
            "examples": [
              8443
            ]
          },
          "cidr_list": {
            "type": "array",
            "description": "Source addresses allowed to connect, as IPv4 CIDRs (at most 20). Leave out for anywhere.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "0.0.0.0/0"
              ]
            ]
          },
          "instance_ids": {
            "type": "array",
            "description": "Instances to spread traffic across (at most 50). You can add them later.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
              ]
            ]
          }
        }
      },
      "UpdateLoadBalancerRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "A new name, 1 to 63 characters.",
            "examples": [
              "web"
            ]
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "roundrobin",
              "leastconn",
              "source"
            ]
          },
          "instance_ids": {
            "type": "array",
            "description": "The whole new set of targets (at most 50). Send `[]` to remove them all.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
              ]
            ]
          }
        }
      },
      "LoadBalancerMember": {
        "type": "object",
        "required": [
          "instance_id",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "instance_id": {
            "type": "string"
          },
          "instance_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The instance's name; null when it is gone."
          },
          "desired_state": {
            "type": "string",
            "description": "`present` while it should receive traffic; `deleted` once you removed it and that has not finished.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "`active` once it receives traffic.",
            "enum": [
              "pending",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          }
        }
      },
      "LoadBalancer": {
        "type": "object",
        "required": [
          "id",
          "name",
          "zone_id",
          "kind",
          "public_ip_id",
          "public_ip_address",
          "network_id",
          "subnet_id",
          "protocol",
          "algorithm",
          "public_port",
          "private_port",
          "cidr_list",
          "members",
          "desired_state",
          "observed_state",
          "in_sync",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `lb_...`."
          },
          "name": {
            "type": "string"
          },
          "zone_id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "vpc_native",
              "appliance"
            ]
          },
          "public_ip_id": {
            "type": "string"
          },
          "public_ip_address": {
            "type": [
              "string",
              "null"
            ],
            "description": "The address clients connect to; null until it is known."
          },
          "network_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subnet_id": {
            "type": "string"
          },
          "protocol": {
            "type": "string",
            "enum": [
              "tcp",
              "http",
              "https"
            ]
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "roundrobin",
              "leastconn",
              "source"
            ]
          },
          "public_port": {
            "type": "integer"
          },
          "private_port": {
            "type": "integer"
          },
          "cidr_list": {
            "type": "array",
            "description": "Source addresses allowed to connect; empty is anywhere.",
            "items": {
              "type": "string"
            }
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LoadBalancerMember"
            }
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "`active` once it serves traffic.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "in_sync": {
            "type": "boolean",
            "description": "False while a change you made has not reached the load balancer yet."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "LoadBalancerList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LoadBalancer"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "KubernetesVersion": {
        "type": "object",
        "required": [
          "id",
          "zone_id",
          "version",
          "status",
          "min_cpu",
          "min_memory_mb"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `k8sv_...`."
          },
          "zone_id": {
            "type": "string"
          },
          "version": {
            "type": "string",
            "examples": [
              "1.31.2"
            ]
          },
          "status": {
            "type": "string",
            "description": "`withdrawn` versions take no new clusters.",
            "enum": [
              "available",
              "withdrawn"
            ]
          },
          "min_cpu": {
            "type": "integer",
            "description": "The fewest vCPUs a node plan needs for this version."
          },
          "min_memory_mb": {
            "type": "integer",
            "description": "The least memory, in MB, a node plan needs for this version."
          }
        }
      },
      "KubernetesVersionList": {
        "type": "object",
        "required": [
          "data",
          "ha_zone_ids"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KubernetesVersion"
            }
          },
          "ha_zone_ids": {
            "type": "array",
            "description": "Zones where a cluster can have 3 control nodes.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CreateKubernetesClusterRequest": {
        "type": "object",
        "required": [
          "name",
          "zone_id",
          "kubernetes_version_id",
          "node_plan"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 40 lowercase letters, digits and hyphens, starting with a letter.",
            "examples": [
              "prod-web"
            ]
          },
          "zone_id": {
            "type": "string",
            "examples": [
              "zone_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "kubernetes_version_id": {
            "type": "string",
            "description": "From the Kubernetes versions list, in `zone_id`.",
            "examples": [
              "k8sv_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "subnet_id": {
            "type": "string",
            "description": "Required in a VPC zone: the subnet the nodes go in. Leave out in a standard zone.",
            "examples": [
              "snet_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "node_plan": {
            "type": "string",
            "description": "The plan slug every node uses, from the plans list. In a zone where every node has one fixed size (af-abj-2: 2 vCPU, 4 GB), the plan must be that size: `422 KUBERNETES_PLAN_NOT_IN_ZONE` on `node_plan`.",
            "examples": [
              "s-2vcpu-4gb"
            ]
          },
          "control_nodes": {
            "type": "integer",
            "default": 1,
            "description": "1, or 3 for a highly available control plane where the zone offers it.",
            "enum": [
              1,
              3
            ]
          },
          "workers": {
            "type": "integer",
            "description": "Worker nodes, 1 to 10. Required unless `autoscaling` is enabled, when it defaults to `min_workers` and must lie within the range.",
            "minimum": 1,
            "maximum": 10,
            "examples": [
              2
            ]
          },
          "autoscaling": {
            "$ref": "#/components/schemas/KubernetesAutoscaling"
          },
          "api_allowed_cidrs": {
            "type": "array",
            "description": "VPC zone only: the IPv4 CIDRs allowed to reach the API server (at most 20). Leave out for any address.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "203.0.113.0/24"
              ]
            ]
          },
          "kind": {
            "type": "string",
            "description": "Cluster architecture. Only `appliance` (the default) is offered: nodes are VMs in your account running k3s. Any other value is `422 INVALID_KUBERNETES_KIND`.",
            "enum": [
              "appliance"
            ],
            "examples": [
              "appliance"
            ]
          },
          "cni_plugin": {
            "type": "string",
            "description": "CNI backend plugin (`flannel`, `wireguard`, or `calico`). Defaults to `flannel`.",
            "examples": [
              "flannel"
            ]
          },
          "pod_cidr": {
            "type": "string",
            "description": "IPv4 CIDR range allocated for cluster pods. Defaults to `10.42.0.0/16`.",
            "examples": [
              "10.42.0.0/16"
            ]
          },
          "service_cidr": {
            "type": "string",
            "description": "IPv4 CIDR range allocated for cluster services. Defaults to `10.43.0.0/16`.",
            "examples": [
              "10.43.0.0/16"
            ]
          },
          "endpoint_access": {
            "type": "string",
            "enum": [
              "private",
              "public",
              "dual"
            ],
            "default": "private",
            "description": "Who can reach the API server. `private` (the default) is reachable only from inside the VPC. `public` and `dual` give the API server a public address of its own, billed as a VPC public IP for every hour it is held.",
            "examples": [
              "private"
            ]
          }
        }
      },
      "KubernetesAutoscaling": {
        "type": "object",
        "description": "The platform's autoscaler: about once a minute it adds a worker when a pod that a worker could run is waiting for room, and removes the newest worker once it has run nothing but DaemonSet pods for 10 minutes, one step at a time and always within min_workers and max_workers. You pay for the workers that run.",
        "required": [
          "enabled",
          "min_workers",
          "max_workers"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "The cluster autoscaler adds and removes workers within the range as pods need them."
          },
          "min_workers": {
            "type": "integer",
            "description": "1 to 10 when enabled; 0 when not.",
            "examples": [
              2
            ]
          },
          "max_workers": {
            "type": "integer",
            "description": "min_workers to 10 when enabled; 0 when not. Billing and your account limits are checked for the maximum.",
            "examples": [
              5
            ]
          }
        }
      },
      "UpdateKubernetesClusterRequest": {
        "type": "object",
        "description": "Send any of the fields; those left out stay as they are.",
        "properties": {
          "workers": {
            "type": "integer",
            "description": "A fixed worker count, 1 to 10. Not with autoscaling enabled: the autoscaler sets it.",
            "minimum": 1,
            "maximum": 10,
            "examples": [
              3
            ]
          },
          "autoscaling": {
            "$ref": "#/components/schemas/KubernetesAutoscaling"
          },
          "api_allowed_cidrs": {
            "type": "array",
            "description": "VPC zone only: the whole new list of IPv4 CIDRs allowed to reach the API server. Send `[]` to allow any address.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "203.0.113.0/24"
              ]
            ]
          }
        }
      },
      "UpgradeKubernetesClusterRequest": {
        "type": "object",
        "required": [
          "kubernetes_version_id"
        ],
        "properties": {
          "kubernetes_version_id": {
            "type": "string",
            "description": "One of the cluster's `available_upgrades`.",
            "examples": [
              "k8sv_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          }
        }
      },
      "ResizeKubernetesClusterPlanRequest": {
        "type": "object",
        "required": [
          "node_plan"
        ],
        "properties": {
          "node_plan": {
            "type": "string",
            "description": "The new node plan slug, from the plans list. In a zone with one fixed node size the plan must be that size (`422 KUBERNETES_PLAN_NOT_IN_ZONE`).",
            "examples": [
              "s-2vcpu-4gb"
            ]
          }
        }
      },
      "UpgradeKubernetesNetworkRequest": {
        "type": "object",
        "properties": {
          "cni_plugin": {
            "type": "string",
            "description": "The new CNI plugin (`flannel`, `wireguard`, or `calico`).",
            "examples": [
              "wireguard"
            ]
          },
          "pod_cidr": {
            "type": "string",
            "description": "The new IPv4 CIDR range allocated for cluster pods.",
            "examples": [
              "10.42.0.0/16"
            ]
          },
          "service_cidr": {
            "type": "string",
            "description": "The new IPv4 CIDR range allocated for cluster services.",
            "examples": [
              "10.43.0.0/16"
            ]
          },
          "api_allowed_cidrs": {
            "type": "array",
            "description": "The new allowed IPv4 CIDRs reaching the API server.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "203.0.113.0/24"
              ]
            ]
          }
        }
      },
      "KubernetesNode": {
        "type": "object",
        "required": [
          "vcpu",
          "memory_mb",
          "disk_gb"
        ],
        "properties": {
          "vcpu": {
            "type": "integer"
          },
          "memory_mb": {
            "type": "integer"
          },
          "disk_gb": {
            "type": "integer"
          }
        }
      },
      "KubernetesCluster": {
        "type": "object",
        "required": [
          "id",
          "name",
          "zone_id",
          "kubernetes_version_id",
          "kubernetes_version",
          "network_id",
          "subnet_id",
          "node_plan_id",
          "node",
          "control_nodes",
          "workers",
          "nodes",
          "desired_state",
          "observed_state",
          "in_sync",
          "failure_code",
          "failure_reason",
          "available_upgrades",
          "autoscaling",
          "api_allowed_cidrs",
          "endpoint",
          "volume_storage_gb",
          "kind",
          "cni_plugin",
          "pod_cidr",
          "service_cidr",
          "endpoint_access",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `k8s_...`."
          },
          "name": {
            "type": "string"
          },
          "zone_id": {
            "type": "string"
          },
          "kubernetes_version_id": {
            "type": "string"
          },
          "kubernetes_version": {
            "type": "string",
            "examples": [
              "1.31.2"
            ]
          },
          "network_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The private network (VPC) the nodes are in; null in a standard zone."
          },
          "subnet_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "node_plan_id": {
            "type": "string"
          },
          "node": {
            "$ref": "#/components/schemas/KubernetesNode"
          },
          "control_nodes": {
            "type": "integer"
          },
          "workers": {
            "type": "integer"
          },
          "nodes": {
            "type": "integer",
            "description": "control_nodes plus workers: the VMs billed."
          },
          "desired_state": {
            "type": "string",
            "enum": [
              "running",
              "stopped",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "`updating` while a scale or upgrade runs.",
            "enum": [
              "pending",
              "provisioning",
              "running",
              "updating",
              "stopping",
              "stopped",
              "retired",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "in_sync": {
            "type": "boolean",
            "description": "False while a scale or upgrade has not finished."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "failure_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "available_upgrades": {
            "type": "array",
            "description": "Versions this cluster can be upgraded to now.",
            "items": {
              "$ref": "#/components/schemas/KubernetesVersion"
            }
          },
          "autoscaling": {
            "$ref": "#/components/schemas/KubernetesAutoscaling"
          },
          "api_allowed_cidrs": {
            "type": "array",
            "description": "Sources allowed to reach the API server; empty is any address.",
            "items": {
              "type": "string"
            }
          },
          "endpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "The API server's URL, once the cluster has one: the public address when the endpoint is public or dual and one is routed, else the private one."
          },
          "public_ip": {
            "type": [
              "string",
              "null"
            ],
            "description": "The public address the API server is reachable on; null until one is routed, and for a private endpoint.",
            "examples": [
              "203.0.113.20"
            ]
          },
          "public_port": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The public port the API server is reachable on; null until one is routed, and for a private endpoint.",
            "examples": [
              6443
            ]
          },
          "volume_storage_gb": {
            "type": "integer",
            "description": "Storage your workloads' persistent volume claims use, billed with the nodes' disks."
          },
          "kind": {
            "type": "string",
            "description": "Cluster architecture kind, e.g. `appliance`.",
            "examples": [
              "appliance"
            ]
          },
          "cni_plugin": {
            "type": "string",
            "description": "CNI backend plugin (`flannel`, `wireguard`, or `calico`).",
            "examples": [
              "flannel"
            ]
          },
          "pod_cidr": {
            "type": "string",
            "description": "IPv4 CIDR range allocated for cluster pods.",
            "examples": [
              "10.42.0.0/16"
            ]
          },
          "service_cidr": {
            "type": "string",
            "description": "IPv4 CIDR range allocated for cluster services.",
            "examples": [
              "10.43.0.0/16"
            ]
          },
          "endpoint_access": {
            "type": "string",
            "description": "API server endpoint network access mode (`public`, `private`, or `dual`).",
            "enum": [
              "public",
              "private",
              "dual"
            ],
            "examples": [
              "public"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "KubernetesClusterList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KubernetesCluster"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "Kubeconfig": {
        "type": "object",
        "required": [
          "kubeconfig"
        ],
        "properties": {
          "kubeconfig": {
            "type": "string",
            "description": "A kubeconfig file (YAML). Secret: it grants cluster-admin."
          }
        }
      },
      "KubernetesNodePoolTaint": {
        "type": "object",
        "required": [
          "key",
          "value",
          "effect"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "effect": {
            "type": "string",
            "enum": [
              "NoSchedule",
              "PreferNoSchedule",
              "NoExecute"
            ]
          }
        }
      },
      "KubernetesNodePool": {
        "type": "object",
        "required": [
          "id",
          "cluster_id",
          "name",
          "node_plan_id",
          "workers",
          "autoscaling_enabled",
          "min_workers",
          "max_workers",
          "labels",
          "taints",
          "status",
          "observed_workers",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "status": {
            "type": "string",
            "description": "`provisioning` (workers being built), `ready` (every worker has joined), `updating` (a scale in progress), `deleting`, or `unavailable` (a pool made while node pools were a preview, with no node size: delete it and create it again).",
            "enum": [
              "provisioning",
              "ready",
              "updating",
              "deleting",
              "unavailable"
            ]
          },
          "observed_workers": {
            "type": "integer",
            "description": "The pool's workers that have joined the cluster. This is what is billed, never `workers` alone."
          },
          "id": {
            "type": "string",
            "description": "e.g. `k8spool_...`."
          },
          "cluster_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "node_plan_id": {
            "type": "string"
          },
          "workers": {
            "type": "integer"
          },
          "autoscaling_enabled": {
            "type": "boolean"
          },
          "min_workers": {
            "type": "integer"
          },
          "max_workers": {
            "type": "integer"
          },
          "labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "taints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KubernetesNodePoolTaint"
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "KubernetesNodePoolList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KubernetesNodePool"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateKubernetesNodePoolRequest": {
        "type": "object",
        "required": [
          "name",
          "plan_id"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Unique name for the node pool.",
            "examples": [
              "cpu-workers"
            ]
          },
          "plan_id": {
            "type": "string",
            "description": "Compute plan ID or slug for the worker VMs.",
            "examples": [
              "standard-2"
            ]
          },
          "workers": {
            "type": "integer",
            "description": "Worker nodes, 1 to 10. Required unless autoscaling_enabled, when it defaults to min_workers."
          },
          "autoscaling_enabled": {
            "type": "boolean",
            "default": false
          },
          "min_workers": {
            "type": "integer",
            "description": "With autoscaling_enabled: fewest workers, 1 to 10."
          },
          "max_workers": {
            "type": "integer",
            "description": "With autoscaling_enabled: most workers, min_workers to 10. Your credit and limits are checked for this many."
          },
          "labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "taints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KubernetesNodePoolTaint"
            }
          }
        }
      },
      "ScaleKubernetesNodePoolRequest": {
        "type": "object",
        "properties": {
          "workers": {
            "type": "integer",
            "description": "Worker nodes, 1 to 10. Always send the pool's whole size: autoscaling_enabled left out turns autoscaling off."
          },
          "autoscaling_enabled": {
            "type": "boolean"
          },
          "min_workers": {
            "type": "integer"
          },
          "max_workers": {
            "type": "integer"
          }
        }
      },
      "KubernetesClusterAddon": {
        "type": "object",
        "required": [
          "id",
          "cluster_id",
          "name",
          "version",
          "status",
          "enabled",
          "configuration",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `k8saddon_...`."
          },
          "cluster_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "configuration": {
            "type": "string",
            "description": "JSON-encoded add-on configuration."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "KubernetesClusterAddonList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KubernetesClusterAddon"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ToggleKubernetesAddonRequest": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether the add-on should be enabled or disabled."
          }
        }
      },
      "ConfigureKubernetesEndpointAccessRequest": {
        "type": "object",
        "required": [
          "endpoint_access"
        ],
        "properties": {
          "endpoint_access": {
            "type": "string",
            "enum": [
              "public",
              "private",
              "dual"
            ],
            "description": "Endpoint access mode."
          },
          "api_allowed_cidrs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IPv4 CIDRs allowed to connect to the cluster API."
          }
        }
      },
      "CreatePortForwardingRuleRequest": {
        "type": "object",
        "required": [
          "instance_id",
          "protocol",
          "public_port_start"
        ],
        "properties": {
          "instance_id": {
            "type": "string",
            "description": "An instance in the public IP's VPC.",
            "examples": [
              "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "`tcp` or `udp`.",
            "enum": [
              "tcp",
              "udp"
            ]
          },
          "public_port_start": {
            "type": "integer",
            "description": "First public port, 1 to 65535.",
            "examples": [
              443
            ]
          },
          "public_port_end": {
            "type": "integer",
            "description": "Last public port. Defaults to `public_port_start` (one port).",
            "examples": [
              443
            ]
          },
          "private_port_start": {
            "type": "integer",
            "description": "First port on the instance. Defaults to `public_port_start`.",
            "examples": [
              8443
            ]
          },
          "private_port_end": {
            "type": "integer",
            "description": "Last port on the instance; the private range must be as wide as the public one. Defaults to match it.",
            "examples": [
              8443
            ]
          }
        }
      },
      "CreatePublicIPRequest": {
        "type": "object",
        "required": [
          "network_id"
        ],
        "properties": {
          "network_id": {
            "type": "string",
            "description": "The VPC network to allocate the address in. It must be active.",
            "examples": [
              "net_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "purpose": {
            "type": "string",
            "default": "static_nat",
            "description": "`static_nat` maps every port to one instance (`instance_id`). `port_forwarding` carries per-port rules instead, and `load_balancer` carries load balancers. Defaults to `static_nat`.",
            "enum": [
              "static_nat",
              "port_forwarding",
              "load_balancer"
            ]
          },
          "instance_id": {
            "type": "string",
            "description": "For `static_nat` only: an instance in `network_id` without a public IP. Leave it out to reserve the address now and attach it later (`POST /public/v1/public-ips/{public_ip_id}/attach`). Leave out for `port_forwarding` and `load_balancer`.",
            "examples": [
              "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          }
        }
      },
      "CreateSSHKeyRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters, unique among your SSH keys.",
            "minLength": 1,
            "maxLength": 255,
            "examples": [
              "deploy"
            ]
          },
          "public_key": {
            "type": "string",
            "description": "One OpenSSH public key line, e.g. `ssh-ed25519 AAAA… deploy@ci`. Leave out to have a key pair generated; its private key is then returned once.",
            "examples": [
              "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample deploy@ci"
            ]
          }
        }
      },
      "CreateSecurityGroupRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters, unique among your live security groups.",
            "minLength": 1,
            "maxLength": 255,
            "examples": [
              "web"
            ]
          },
          "rules": {
            "type": "array",
            "description": "The group's rules; at least one. Inbound traffic no rule allows is dropped.",
            "items": {
              "$ref": "#/components/schemas/SecurityGroupRule"
            }
          }
        }
      },
      "ResizeDatabaseStorageRequest": {
        "type": "object",
        "required": [
          "storage_gb"
        ],
        "properties": {
          "storage_gb": {
            "type": "integer",
            "minimum": 1,
            "description": "The new data disk size in GB: larger than the current `data_volume_size_gb`, at most the zone's `max_gb` (2000 today) and a multiple of its `step_gb` (10 today); see `storage` in `GET /public/v1/database-engines`. It only grows.",
            "examples": [
              100
            ]
          }
        }
      },
      "CreateSnapshotRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters, unique among this resource's snapshots, e.g. `pre-upgrade`.",
            "minLength": 1,
            "maxLength": 255,
            "examples": [
              "pre-upgrade"
            ]
          }
        }
      },
      "CreateSubnetRequest": {
        "type": "object",
        "required": [
          "name",
          "cidr"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters.",
            "minLength": 1,
            "maxLength": 255,
            "examples": [
              "app"
            ]
          },
          "cidr": {
            "type": "string",
            "description": "An IPv4 range inside the VPC's CIDR that does not overlap its other subnets, e.g. `10.0.1.0/24`.",
            "examples": [
              "10.0.1.0/24"
            ]
          }
        }
      },
      "CreateVolumeRequest": {
        "type": "object",
        "required": [
          "name",
          "disk_offering_slug"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "1 to 255 characters.",
            "minLength": 1,
            "maxLength": 255,
            "examples": [
              "data"
            ]
          },
          "disk_offering_slug": {
            "type": "string",
            "description": "The volume type, from `GET /public/v1/disk-offerings`.",
            "examples": [
              "medium-20gb"
            ]
          },
          "size_gb": {
            "type": "integer",
            "description": "Size in GB. Required for an offering with `custom_size: true`; ignored otherwise.",
            "examples": [
              100
            ]
          },
          "region": {
            "type": "string",
            "description": "A region from `GET /public/v1/regions`. Defaults to the platform's region.",
            "examples": [
              "af-abj"
            ]
          },
          "instance_id": {
            "type": "string",
            "description": "Attach the new volume at once to this running instance in the same zone.",
            "examples": [
              "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "mount_point": {
            "type": "string",
            "description": "With `instance_id`: an absolute path to mount the volume at, e.g. `/data`.",
            "examples": [
              "/data"
            ]
          },
          "encrypted": {
            "type": "boolean",
            "description": "Optional. `true` asks for an **encrypted data volume**. It is a request, not encryption yet: the volume reports `encryption.status` `requested` until its disk has been formatted with a key from Pantech, and `encrypted` only once the platform has confirmed that. The format happens inside the instance, by the Pantech volume agent (`pantech-vkey`): attach the volume to an instance that runs the agent and it formats the new, empty disk for you as soon as it appears, so you only create a filesystem on `/dev/mapper/pvk-...` and mount it. Creating or attaching alone encrypts nothing, an instance without the agent cannot encrypt it, and a disk that already holds data is never formatted. Its key is released only to the instance of your organization the volume is attached to, so the volume can be used with any instance that runs the agent, an encrypted VM or a plain one. Refused with `ENCRYPTION_NOT_SUPPORTED` when encrypted volumes are not enabled for your organization, and `ENCRYPTED_VOLUMES_UNAVAILABLE` while the service is off. `false` or omitted creates a plain volume, as before.",
            "examples": [
              true
            ]
          }
        }
      },
      "ChangeDatabasePasswordRequest": {
        "type": "object",
        "required": [
          "password"
        ],
        "properties": {
          "password": {
            "type": "string",
            "minLength": 16,
            "maxLength": 128,
            "writeOnly": true,
            "description": "The new admin password: 16 to 128 printable ASCII characters, with no spaces, single quotes (`'`), double quotes (`\"`) or backslashes (`\\`). Write-only: never stored in plain text, never returned, never logged.",
            "pattern": "^[!#-&(-\\[\\]-~]{16,128}$",
            "examples": [
              "c0rrect-H0rse-battery-St4ple"
            ]
          }
        }
      },
      "CreateDatabaseRequest": {
        "type": "object",
        "required": [
          "name",
          "engine",
          "version",
          "plan_slug",
          "zone_id"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "1 to 255 characters, unique among your databases.",
            "examples": [
              "orders-db"
            ]
          },
          "engine": {
            "type": "string",
            "description": "`postgresql`, `mysql` or `mariadb`; see `GET /public/v1/database-engines`.",
            "enum": [
              "postgresql",
              "mysql",
              "mariadb"
            ]
          },
          "version": {
            "type": "string",
            "description": "A version line offered for `engine` in `zone_id`, from `GET /public/v1/database-engines`, e.g. `18` for PostgreSQL or `8.4` for MySQL.",
            "examples": [
              "18"
            ]
          },
          "plan_slug": {
            "type": "string",
            "description": "The size, from `GET /public/v1/plans`: its vCPU and memory, and its `disk_gb` as the smallest data disk.",
            "examples": [
              "starter"
            ]
          },
          "zone_id": {
            "type": "string",
            "description": "Where to create it: a zone from the version's `zones`, e.g. `af-abj-1` (standard) or `af-abj-2` (VPC).",
            "examples": [
              "af-abj-2"
            ]
          },
          "subnet_id": {
            "type": "string",
            "description": "Required in a VPC zone (`af-abj-2`): one of your subnets there, which the database joins. Leave out in a standard zone.",
            "examples": [
              "snet_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "access_rules": {
            "type": "array",
            "maxItems": 50,
            "description": "The initial allow-list: IPv4 CIDRs with a prefix of `/8` or longer, never `0.0.0.0/0`, at most 50, no range twice. Leave out for the zone's default (the subnet's VPC CIDR in a VPC zone, nobody in a standard zone); send `[]` for nobody.",
            "examples": [
              [
                "10.0.1.0/24",
                "10.250.3.17/32"
              ]
            ],
            "items": {
              "type": "string"
            }
          },
          "admin_username": {
            "type": "string",
            "minLength": 3,
            "maxLength": 32,
            "pattern": "^[a-z][a-z0-9_]{2,31}$",
            "description": "The admin login's name: 3 to 32 characters, lowercase letters, digits and underscores, starting with a letter. Reserved, and refused with `INVALID_DATABASE_ADMIN_USERNAME`: `root`, `postgres`, `public`, `none`, `all`, `user`, `sys`, `system`, `replication`, `current_user`, `current_role`, `session_user`, and any name starting with `pg_`, `mysql`, `mariadb` or `pantech`. Not secret. Defaults to `dbadmin`.",
            "default": "dbadmin",
            "examples": [
              "app_admin"
            ]
          },
          "password": {
            "type": "string",
            "minLength": 16,
            "maxLength": 128,
            "writeOnly": true,
            "description": "Optional admin password: 16 to 128 printable ASCII characters, with no spaces, single quotes (`'`), double quotes (`\"`) or backslashes (`\\`). Write-only: never stored in plain text, never returned, never logged. Leave it out to have a 32-character password generated and returned once in the response.",
            "pattern": "^[!#-&(-\\[\\]-~]{16,128}$",
            "examples": [
              "c0rrect-H0rse-battery-St4ple"
            ]
          },
          "storage_gb": {
            "type": "integer",
            "minimum": 1,
            "description": "Data disk size in GB. Leave out for the plan's `disk_gb`. Otherwise at least the plan's `disk_gb` (or the zone's `min_gb` when larger), at most the zone's `max_gb` (2000 today), and above that base a multiple of the zone's `step_gb` (10 today); the base itself is always allowed. Read the zone's limits and price from `storage` in `GET /public/v1/database-engines` rather than hard-coding them. The upfront payment and the hourly storage price use this size. It can be grown later, never shrunk.",
            "examples": [
              100
            ]
          }
        }
      },
      "Database": {
        "type": "object",
        "required": [
          "id",
          "name",
          "engine",
          "version",
          "port",
          "plan_id",
          "data_volume_size_gb",
          "pending_data_volume_size_gb",
          "zone_id",
          "subnet_id",
          "hostname",
          "private_ip",
          "desired_state",
          "observed_state",
          "generation",
          "observed_generation",
          "access_rules",
          "failure_code",
          "created_at",
          "updated_at",
          "admin_username",
          "security_group_ids",
          "effective_access_rules",
          "ignored_security_group_rules"
        ],
        "properties": {
          "admin_username": {
            "type": "string",
            "description": "The admin login to connect as: the one chosen at create, or `dbadmin`. `pantech_admin` for a database created before the login could be chosen.",
            "examples": [
              "dbadmin"
            ]
          },
          "security_group_ids": {
            "type": "array",
            "description": "Your security groups attached to the database, in the order attached (at most 5). `[]` when none.",
            "items": {
              "type": "string"
            }
          },
          "effective_access_rules": {
            "type": "array",
            "description": "The allow-list as the database applies it: its own `access_rules` plus the ranges its security groups add, each range once under its first source. In effect once `observed_generation` equals `generation`.",
            "items": {
              "$ref": "#/components/schemas/DatabaseEffectiveAccessRule"
            }
          },
          "ignored_security_group_rules": {
            "type": "array",
            "description": "Rules of the attached security groups that add nothing to the database, and why. `[]` when none.",
            "items": {
              "$ref": "#/components/schemas/DatabaseIgnoredSecurityGroupRule"
            }
          },
          "id": {
            "type": "string",
            "description": "The database's id, `db_` followed by 26 characters.",
            "readOnly": true,
            "examples": [
              "db_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among your databases.",
            "examples": [
              "orders-db"
            ]
          },
          "engine": {
            "type": "string",
            "description": "`postgresql`, `mysql` or `mariadb`.",
            "enum": [
              "postgresql",
              "mysql",
              "mariadb"
            ]
          },
          "version": {
            "type": "string",
            "description": "The engine's version line, e.g. `18` or `8.4`. Minor updates within the line are applied by the platform.",
            "examples": [
              "18"
            ]
          },
          "port": {
            "type": "integer",
            "description": "The TCP port to connect to: 5432 for PostgreSQL, 3306 for MySQL and MariaDB.",
            "examples": [
              5432
            ]
          },
          "plan_id": {
            "type": "string",
            "description": "The plan setting its vCPU and memory.",
            "examples": [
              "plan_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "data_volume_size_gb": {
            "type": "integer",
            "description": "The data disk's size in GB, as in place and billed.",
            "examples": [
              80
            ]
          },
          "pending_data_volume_size_gb": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The size a storage resize in flight is growing the data disk to; null when none."
          },
          "zone_id": {
            "type": "string",
            "description": "The zone it runs in, e.g. `af-abj-2`.",
            "examples": [
              "af-abj-2"
            ]
          },
          "subnet_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its VPC subnet in a VPC zone; null in a standard zone."
          },
          "hostname": {
            "type": [
              "string",
              "null"
            ],
            "description": "The name to connect to, e.g. `db-7k2q9x4m1a.af-abj-2.db.pantechdynamics.com`. It resolves to `private_ip` and works only from where that address is reachable. Null until assigned.",
            "examples": [
              "db-7k2q9x4m1a.af-abj-2.db.pantechdynamics.com"
            ]
          },
          "private_ip": {
            "type": [
              "string",
              "null"
            ],
            "description": "The database's private address, never public. Null until assigned.",
            "examples": [
              "10.0.1.12"
            ]
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `running`, `stopped` or `deleted`.",
            "enum": [
              "running",
              "stopped",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed. A change is complete when it matches `desired_state`; `failed` means the last change could not be made (see the failure fields), and `unknown` means the platform could not check.",
            "enum": [
              "pending",
              "provisioning",
              "running",
              "stopping",
              "stopped",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "generation": {
            "type": "integer",
            "description": "Increases by one with every change you request.",
            "readOnly": true
          },
          "observed_generation": {
            "type": "integer",
            "description": "The `generation` last applied: equal to `generation` once the last change (access rules, security groups, password) is in effect.",
            "readOnly": true
          },
          "access_rules": {
            "type": "array",
            "description": "The database's own allow-list, as set at create or with *Replace access rules*.",
            "items": {
              "$ref": "#/components/schemas/DatabaseAccessRule"
            }
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "A stable code for why the last change failed; null when nothing failed. The failed operation's `failure.reason` explains it."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "DatabaseAccessRule": {
        "type": "object",
        "required": [
          "cidr",
          "protocol",
          "port"
        ],
        "properties": {
          "cidr": {
            "type": "string",
            "description": "An allowed IPv4 range, in canonical form.",
            "examples": [
              "10.0.1.0/24"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "Always `tcp`.",
            "enum": [
              "tcp"
            ]
          },
          "port": {
            "type": "integer",
            "description": "The engine's port: 5432 or 3306.",
            "examples": [
              5432
            ]
          }
        }
      },
      "DatabaseEffectiveAccessRule": {
        "type": "object",
        "required": [
          "cidr",
          "protocol",
          "port",
          "source"
        ],
        "properties": {
          "cidr": {
            "type": "string",
            "description": "An allowed IPv4 range, in canonical form.",
            "examples": [
              "10.0.1.0/24"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "Always `tcp`.",
            "enum": [
              "tcp"
            ]
          },
          "port": {
            "type": "integer",
            "description": "The engine's port: 5432 or 3306.",
            "examples": [
              5432
            ]
          },
          "source": {
            "type": "string",
            "description": "Where the range comes from: `access_rule`, or `security_group:` followed by the group's id (e.g. `security_group:sg_…`).",
            "examples": [
              "access_rule"
            ]
          }
        }
      },
      "DatabaseIgnoredSecurityGroupRule": {
        "type": "object",
        "required": [
          "security_group_id",
          "direction",
          "protocol",
          "port_range",
          "cidr",
          "reason"
        ],
        "properties": {
          "security_group_id": {
            "type": "string",
            "description": "The attached group the rule belongs to."
          },
          "direction": {
            "type": "string",
            "description": "The rule's direction.",
            "enum": [
              "ingress",
              "egress"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "The rule's protocol.",
            "enum": [
              "tcp",
              "udp",
              "icmp",
              "all"
            ]
          },
          "port_range": {
            "type": [
              "string",
              "null"
            ],
            "description": "`80`, `3000-4000`, or null for all ports."
          },
          "cidr": {
            "type": "string",
            "description": "The rule's CIDR.",
            "examples": [
              "0.0.0.0/0"
            ]
          },
          "reason": {
            "type": "string",
            "description": "Why it adds nothing: `egress_rule`, `protocol_not_tcp` (udp or icmp), `port_not_covered` (its ports exclude the engine's), `cidr_too_wide` (wider than /8, including `0.0.0.0/0`) or `cidr_not_ipv4`.",
            "enum": [
              "egress_rule",
              "protocol_not_tcp",
              "port_not_covered",
              "cidr_too_wide",
              "cidr_not_ipv4"
            ]
          }
        }
      },
      "SetDatabaseSecurityGroupsRequest": {
        "type": "object",
        "required": [
          "security_group_ids"
        ],
        "properties": {
          "security_group_ids": {
            "type": "array",
            "maxItems": 5,
            "description": "The complete set to attach: at most 5 distinct ids of your own security groups in the database's zone, e.g. `sg_…`. `[]` detaches every group.",
            "uniqueItems": true,
            "examples": [
              [
                "sg_06gk3x9tq7m2v8r4y1c5d0zp8w"
              ]
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "DatabaseAccessRuleRequest": {
        "type": "object",
        "required": [
          "cidr"
        ],
        "properties": {
          "cidr": {
            "type": "string",
            "description": "One IPv4 CIDR to allow, with a prefix of `/8` to `/32`; never `0.0.0.0/0`. Host bits are masked (`10.0.1.7/24` is stored as `10.0.1.0/24`). Use `/32` for one address, such as an instance's `private_network_ip`.",
            "examples": [
              "10.250.3.17/32"
            ]
          }
        }
      },
      "DatabaseEngine": {
        "type": "object",
        "required": [
          "engine",
          "display_name",
          "port",
          "versions",
          "storage"
        ],
        "properties": {
          "engine": {
            "type": "string",
            "description": "The value `engine` takes in *Create a database*: `postgresql`, `mysql` or `mariadb`.",
            "examples": [
              "postgresql"
            ]
          },
          "display_name": {
            "type": "string",
            "description": "The engine's name for display.",
            "examples": [
              "PostgreSQL"
            ]
          },
          "port": {
            "type": "integer",
            "description": "The port its databases listen on: 5432 or 3306.",
            "examples": [
              5432
            ]
          },
          "versions": {
            "type": "array",
            "description": "Version lines offered for new databases, long-term-support lines only. Empty when none is offered right now.",
            "items": {
              "type": "object",
              "required": [
                "version",
                "eol_date",
                "zones"
              ],
              "properties": {
                "version": {
                  "type": "string"
                },
                "eol_date": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                },
                "zones": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "storage": {
            "type": "array",
            "description": "The data disk sizes a new database of this engine may have, per zone: use them for `storage_gb` in *Create a database* and *Grow a database's storage*. One entry per zone where a version of this engine can be created and database storage is available. Read the allowed sizes from here rather than hard-coding them.",
            "items": {
              "type": "object",
              "required": [
                "zone_id",
                "min_gb",
                "min_is_plan_disk",
                "max_gb",
                "step_gb",
                "price_per_gb_month_minor",
                "currency"
              ],
              "properties": {
                "zone_id": {
                  "type": "string",
                  "description": "The zone, e.g. `af-abj-2`.",
                  "examples": [
                    "af-abj-2"
                  ]
                },
                "min_gb": {
                  "type": "integer",
                  "description": "The zone's minimum data disk in GB. 0 means the plan's `disk_gb` is the minimum; otherwise the minimum is the larger of the plan's `disk_gb` and this value.",
                  "minimum": 0,
                  "examples": [
                    0
                  ]
                },
                "min_is_plan_disk": {
                  "type": "boolean",
                  "description": "True when `min_gb` is 0, so the chosen plan's `disk_gb` is the minimum."
                },
                "max_gb": {
                  "type": "integer",
                  "description": "The largest data disk in GB.",
                  "examples": [
                    2000
                  ]
                },
                "step_gb": {
                  "type": "integer",
                  "description": "Above the base size (the minimum), `storage_gb` must be a multiple of this.",
                  "examples": [
                    10
                  ]
                },
                "price_per_gb_month_minor": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "format": "int64",
                  "description": "Price of one GB of data disk for a 730-hour month, in minor units of `currency`; null when it could not be priced."
                },
                "currency": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "`NGN` or `USD`; null when not priced."
                }
              }
            }
          }
        }
      },
      "DatabaseEngineList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatabaseEngine"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "DatabaseList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Database"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "DatabaseOrder": {
        "type": "object",
        "description": "How a new database is paid for and provisioned. Never includes a password. The console API returns the same order, naming the id `order_id`.",
        "required": [
          "id",
          "order_id",
          "attempt_id",
          "database_id",
          "status",
          "operation_id",
          "failure_code",
          "amount_minor",
          "currency",
          "created_at",
          "updated_at",
          "admin_username"
        ],
        "properties": {
          "admin_username": {
            "type": "string",
            "description": "The admin login the database is created with."
          },
          "id": {
            "type": "string",
            "description": "The order's id, `ord_…`.",
            "readOnly": true
          },
          "order_id": {
            "type": "string",
            "description": "The same value as `id`."
          },
          "attempt_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The card payment attempt; null when the order was paid from credit or not charged yet."
          },
          "database_id": {
            "type": "string",
            "description": "The id the database has, or will have once provisioned."
          },
          "status": {
            "type": "string",
            "description": "`awaiting_payment`, then `paid`, `provisioning` and `provisioned` (final: the database exists). `payment_failed` (no payment could be taken; nothing charged, or it was returned) and `failed` (provisioning could not start; any payment taken is returned to your credit) are final too.",
            "enum": [
              "awaiting_payment",
              "paid",
              "provisioning",
              "provisioned",
              "payment_failed",
              "failed"
            ]
          },
          "operation_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The database's create operation, set once provisioning starts; null before."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the order failed, when it did: e.g. `insufficient_credit`, `card_declined`, `payment_expired` (not paid within an hour), `database_name_taken`, `provisioning_failed`. Null otherwise. `organization_deleted`: the order was cancelled because its organization was deleted; any payment taken is returned to credit."
          },
          "amount_minor": {
            "type": "integer",
            "format": "int64",
            "description": "The initial payment in minor units of `currency` (kobo or cents)."
          },
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`: your organization's billing currency.",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "DatabaseOrderList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatabaseOrder"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "DatabaseOrderAccepted": {
        "type": "object",
        "description": "Returned with `202 Accepted` by `POST /public/v1/databases`, with `Cache-Control: no-store`: the order that pays for and then provisions the database.",
        "required": [
          "order_id",
          "database_id",
          "resource_id",
          "status",
          "operation_id",
          "failure_code",
          "amount_minor",
          "currency",
          "password_returned",
          "password",
          "admin_username"
        ],
        "properties": {
          "admin_username": {
            "type": "string",
            "description": "The admin login the database is created with: the one you sent, or `dbadmin`."
          },
          "order_id": {
            "type": "string",
            "description": "Follow it at `GET /public/v1/database-orders/{order_id}` (also the `Location` header)."
          },
          "database_id": {
            "type": "string",
            "description": "The id the database will have."
          },
          "resource_id": {
            "type": "string",
            "description": "Same as `database_id`."
          },
          "status": {
            "type": "string",
            "description": "The order's status now, usually `awaiting_payment`. See `DatabaseOrder.status`.",
            "enum": [
              "awaiting_payment",
              "paid",
              "provisioning",
              "provisioned",
              "payment_failed",
              "failed"
            ]
          },
          "operation_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set once provisioning starts."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null for a new order; on a retry, the order's `failure_code` if it has failed since."
          },
          "amount_minor": {
            "type": "integer",
            "description": "The initial payment, in minor units (kobo or cents): the price of an instance of the same plan with no public address.",
            "format": "int64"
          },
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`: your organization's billing currency.",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "password_returned": {
            "type": "boolean",
            "description": "True only when the password was generated for you and this request created the order. Otherwise `password` is null: you chose the password, or this is a retry."
          },
          "password": {
            "type": [
              "string",
              "null"
            ],
            "description": "The generated admin password (32 letters and digits), in this response only. Store it securely now: it is never readable again. Null when you chose the password or on a retry.",
            "examples": [
              "q8Vn3TzK1mXw7RbLc4Hs9JdP2fYa6GeU"
            ]
          }
        }
      },
      "DatabasePasswordAccepted": {
        "type": "object",
        "description": "Returned with `202 Accepted` by `reset-password`, with `Cache-Control: no-store`.",
        "required": [
          "operation_id",
          "resource_id",
          "status",
          "password_returned",
          "password"
        ],
        "properties": {
          "operation_id": {
            "type": "string",
            "description": "The operation carrying out the change. Poll `GET /public/v1/operations/{operation_id}` (also the `Location` header) until `status` is `succeeded` or `failed`."
          },
          "resource_id": {
            "type": "string",
            "description": "The database."
          },
          "status": {
            "type": "string",
            "description": "The operation's status when the request was accepted, usually `submitting`."
          },
          "password_returned": {
            "type": "boolean",
            "description": "False on a retry with the same Idempotency-Key; `password` is then null."
          },
          "password": {
            "type": [
              "string",
              "null"
            ],
            "description": "The generated admin password (32 letters and digits), in this response only. Store it securely now: it is never stored and cannot be read again. Null on a retry.",
            "examples": [
              "q8Vn3TzK1mXw7RbLc4Hs9JdP2fYa6GeU"
            ]
          }
        }
      },
      "DiskOffering": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "custom_size",
          "currency",
          "hourly_price_minor"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "description": "Use this in `disk_offering_slug`."
          },
          "name": {
            "type": "string",
            "description": "Its name for display."
          },
          "size_gb": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Fixed size; null for a custom-size offering."
          },
          "custom_size": {
            "type": "boolean",
            "description": "When true, send `size_gb` on create; the price is then per GB."
          },
          "storage_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "The storage class, e.g. `shared` or `local`; null when not stated."
          },
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`: your organization's currency."
          },
          "hourly_price_minor": {
            "type": "integer",
            "format": "int64",
            "description": "Price per hour in minor units of `currency`: for the whole volume, or per GB for a custom-size offering."
          }
        }
      },
      "DiskOfferingList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DiskOffering"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "Failure": {
        "type": [
          "object",
          "null"
        ],
        "description": "Why it failed, when it did; otherwise null.",
        "required": [
          "code",
          "reason"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "A stable failure code to branch on, e.g. `INSTANCE_BUSY`. Provisioning failures use `PROVISIONING_CAPACITY_UNAVAILABLE` (no capacity in the zone right now: try another plan or zone, or try later), `PROVISIONING_LIMIT_EXCEEDED` (an account limit was reached: delete unused resources or contact support), `PROVISIONING_ADDRESSES_EXHAUSTED` (no free addresses in the zone), `PROVISIONING_IMAGE_UNAVAILABLE` (the image is not ready), `PROVISIONING_RESOURCE_BUSY` (the resource was busy: try again once it settles), `PROVISIONING_RESOURCE_CONFLICT`, `PROVISIONING_RESOURCE_NOT_FOUND`, `PROVISIONING_INVALID_REQUEST`, `PROVISIONING_UNAVAILABLE` (temporarily unavailable: retry), `PROVISIONING_INTERNAL_ERROR` (a fault on our side: our team is alerted, and retrying will not help) and `PROVISIONING_FAILED` (anything else).",
            "examples": [
              "INSTANCE_BUSY"
            ]
          },
          "reason": {
            "type": "string",
            "description": "A readable sentence saying what went wrong and what to do; safe to show to your users. Its wording may change: branch on `code`."
          }
        }
      },
      "FirewallRule": {
        "type": "object",
        "required": [
          "id",
          "subnet_id",
          "number",
          "direction",
          "protocol",
          "cidr",
          "action",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `aclr_...`."
          },
          "subnet_id": {
            "type": "string",
            "description": "The subnet the rule applies to, as a whole."
          },
          "number": {
            "type": "integer",
            "description": "Evaluation order, 100-9999; lowest first.",
            "minimum": 100,
            "maximum": 9999
          },
          "direction": {
            "type": "string",
            "description": "`ingress` (into the subnet) or `egress` (out of it).",
            "enum": [
              "ingress",
              "egress"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "`tcp`, `udp`, `icmp` or `all`.",
            "enum": [
              "tcp",
              "udp",
              "icmp",
              "all"
            ]
          },
          "port_start": {
            "type": [
              "integer",
              "null"
            ],
            "description": "First port, for `tcp`/`udp`; null otherwise."
          },
          "port_end": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Last port, for `tcp`/`udp`; null otherwise."
          },
          "icmp_type": {
            "type": [
              "integer",
              "null"
            ],
            "description": "ICMP type, for `icmp`; null for every type."
          },
          "icmp_code": {
            "type": [
              "integer",
              "null"
            ],
            "description": "ICMP code, for `icmp`; null for every code."
          },
          "cidr": {
            "type": "string",
            "description": "Source (ingress) or destination (egress), e.g. `0.0.0.0/0`."
          },
          "action": {
            "type": "string",
            "description": "`allow` or `deny`.",
            "enum": [
              "allow",
              "deny"
            ]
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "FirewallRuleFields": {
        "type": "object",
        "required": [
          "number",
          "direction",
          "protocol",
          "cidr",
          "action"
        ],
        "properties": {
          "number": {
            "type": "integer",
            "description": "Evaluation order, 100-9999; lowest first.",
            "minimum": 100,
            "maximum": 9999
          },
          "direction": {
            "type": "string",
            "description": "`ingress` (into the subnet) or `egress` (out of it).",
            "enum": [
              "ingress",
              "egress"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "`tcp`, `udp`, `icmp` or `all`.",
            "enum": [
              "tcp",
              "udp",
              "icmp",
              "all"
            ]
          },
          "port_start": {
            "type": [
              "integer",
              "null"
            ],
            "description": "First port, for `tcp`/`udp`; null otherwise."
          },
          "port_end": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Last port, for `tcp`/`udp`; null otherwise."
          },
          "icmp_type": {
            "type": [
              "integer",
              "null"
            ],
            "description": "ICMP type, for `icmp`; null for every type."
          },
          "icmp_code": {
            "type": [
              "integer",
              "null"
            ],
            "description": "ICMP code, for `icmp`; null for every code."
          },
          "cidr": {
            "type": "string",
            "description": "Source (ingress) or destination (egress), e.g. `0.0.0.0/0`."
          },
          "action": {
            "type": "string",
            "description": "`allow` or `deny`.",
            "enum": [
              "allow",
              "deny"
            ]
          }
        }
      },
      "FirewallRuleList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor",
          "system_rules"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FirewallRule"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null."
          },
          "system_rules": {
            "type": "array",
            "description": "The platform's own rules around yours. They always apply and cannot be changed.",
            "items": {
              "$ref": "#/components/schemas/FirewallRuleFields"
            }
          }
        }
      },
      "GeneratedSSHKey": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SSHKey"
          },
          {
            "type": "object",
            "required": [
              "private_key"
            ],
            "properties": {
              "private_key": {
                "type": "string",
                "description": "The private key, in this response only. It is never stored and cannot be fetched again."
              }
            }
          }
        ]
      },
      "Image": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "version",
          "zones"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The image's id.",
            "readOnly": true
          },
          "slug": {
            "type": "string",
            "description": "Use this in `image_slug`."
          },
          "name": {
            "type": "string",
            "description": "Its name for display, e.g. `Ubuntu`."
          },
          "version": {
            "type": "string",
            "description": "Its version, e.g. `24.04`."
          },
          "zones": {
            "type": "array",
            "description": "Zones this image can be deployed in.",
            "items": {
              "type": "string"
            }
          },
          "encrypted": {
            "type": "boolean",
            "description": "True for an encrypted image: the instance's root disk is encrypted on our storage, with its own key, and the instance needs our key servers to start. Encrypted images are listed only for organizations they are enabled for."
          },
          "encrypted_variant_of": {
            "type": [
              "string",
              "null"
            ],
            "description": "On an encrypted image, the slug of the plain image it is the encrypted version of (e.g. `ubuntu-24-04` for `ubuntu-24-04-encrypted`); null otherwise."
          }
        }
      },
      "ImageList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Image"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "Instance": {
        "type": "object",
        "required": [
          "id",
          "name",
          "plan_id",
          "image_id",
          "desired_state",
          "observed_state",
          "tags"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `vm_06gf...`."
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among your instances.",
            "examples": [
              "web-1"
            ]
          },
          "plan_id": {
            "type": "string",
            "description": "The plan's id."
          },
          "plan_slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "The plan's slug, as `plan_slug` takes it (e.g. `starter`); null if the plan has since been retired."
          },
          "image_id": {
            "type": "string",
            "description": "The image's id."
          },
          "image_slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "The image's slug, as `image_slug` takes it (e.g. `ubuntu-24-04`); null if the image has since been retired."
          },
          "encrypted": {
            "type": "boolean",
            "description": "True when the instance runs an encrypted image: its root disk is encrypted on our storage, with its own key."
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `af-abj`."
          },
          "zone": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `af-abj-1`."
          },
          "network_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The VPC, for an instance in one."
          },
          "subnet_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its VPC subnet; null for a standard instance."
          },
          "security_group_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The security group, for a standard instance."
          },
          "public_ipv4": {
            "type": [
              "string",
              "null"
            ],
            "description": "The instance's own public address (standard instances). A VPC instance is reached through a public IP: see `GET /public/v1/public-ips`."
          },
          "private_ipv4": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its private address: in its VPC subnet, or on the zone's guest network."
          },
          "private_network_state": {
            "type": "string",
            "description": "Its interface on the zone's private database network: `none`, `attaching`, `attached` or `detaching`. See *Add a private database network interface*.",
            "enum": [
              "none",
              "attaching",
              "attached",
              "detaching"
            ]
          },
          "deletion_protection": {
            "type": "boolean",
            "description": "Platform VM deletion is refused while true."
          },
          "private_network_ip": {
            "type": [
              "string",
              "null"
            ],
            "description": "That interface's address once attached (kept while it is being removed); null otherwise. Allow it on a managed database as a `/32` access rule.",
            "examples": [
              "10.250.3.17"
            ]
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `running`, `stopped` or `deleted`.",
            "enum": [
              "running",
              "stopped",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed. A change is complete when it matches `desired_state`; `failed` means the last change could not be made (see the failure fields), and `unknown` means the platform could not check.",
            "enum": [
              "pending",
              "provisioning",
              "running",
              "stopping",
              "stopped",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "spec": {
            "type": [
              "object",
              "null"
            ],
            "description": "The capacity this instance was created with.",
            "required": [
              "vcpu",
              "memory_mb",
              "disk_gb"
            ],
            "properties": {
              "vcpu": {
                "type": "integer"
              },
              "memory_mb": {
                "type": "integer"
              },
              "disk_gb": {
                "type": "integer"
              }
            }
          },
          "tags": {
            "type": "object",
            "description": "Your own labels, as sent at create.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "failure": {
            "$ref": "#/components/schemas/Failure",
            "description": "Why the last change failed, when it did; otherwise null."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "InstanceList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Instance"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "InstanceOrder": {
        "type": "object",
        "required": [
          "id",
          "instance_id",
          "status",
          "amount_minor",
          "currency"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `ord_...`."
          },
          "instance_id": {
            "type": "string",
            "description": "The id the instance has, or will have once provisioned."
          },
          "status": {
            "type": "string",
            "description": "`awaiting_payment`, then `paid`, `provisioning` and `provisioned` (final: the instance exists). `payment_failed` and `failed` are final too; any payment taken is returned to your credit.",
            "enum": [
              "awaiting_payment",
              "paid",
              "provisioning",
              "provisioned",
              "payment_failed",
              "failed"
            ]
          },
          "operation_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The instance's create operation, set once provisioning starts."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the order failed, e.g. `insufficient_credit`, `card_declined`, `payment_expired`; null otherwise. `organization_deleted`: the order was cancelled because its organization was deleted; any payment taken is returned to credit."
          },
          "amount_minor": {
            "type": "integer",
            "format": "int64",
            "description": "The initial payment in minor units of `currency`."
          },
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`.",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "InstanceOrderList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceOrder"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "Me": {
        "type": "object",
        "required": [
          "organization_id",
          "project_id",
          "api_key"
        ],
        "properties": {
          "organization_id": {
            "type": "string",
            "description": "The organization the key belongs to.",
            "examples": [
              "org_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "project_id": {
            "type": "string",
            "description": "The organization's project; every resource belongs to it."
          },
          "api_key": {
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "client_name",
              "scopes",
              "expires_at"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "description": "`standard` for a key made under Organization › API keys; `ai_app` for the key an AI app was given when a member connected it.",
                "enum": [
                  "standard",
                  "ai_app"
                ]
              },
              "client_name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The AI app's name as it introduced itself (not verified by Pantech), e.g. `Research assistant`. Null for a standard key.",
                "examples": [
                  "Research assistant"
                ]
              },
              "scopes": {
                "type": "array",
                "description": "`delete` appears only on an AI app's key, together with `write`.",
                "items": {
                  "type": "string",
                  "enum": [
                    "read",
                    "write",
                    "delete"
                  ]
                }
              },
              "expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      },
      "MetricsSeries": {
        "type": "object",
        "required": [
          "interval",
          "available",
          "points"
        ],
        "properties": {
          "interval": {
            "type": "string",
            "description": "The window the points cover: `1h`, `24h`, `7d` or `30d`.",
            "enum": [
              "1h",
              "24h",
              "7d",
              "30d"
            ]
          },
          "available": {
            "type": "boolean",
            "description": "False when no samples exist yet, for example just after the instance was created."
          },
          "sampled_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the newest sample was taken; null when none."
          },
          "points": {
            "type": "array",
            "description": "One point per bucket, oldest first. A null value means no sample in that bucket.",
            "items": {
              "type": "object",
              "required": [
                "bucket_start",
                "bucket_end"
              ],
              "properties": {
                "bucket_start": {
                  "type": "string",
                  "format": "date-time"
                },
                "bucket_end": {
                  "type": "string",
                  "format": "date-time"
                },
                "cpu_percent": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "memory_percent": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "network_in_bytes": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "network_out_bytes": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "disk_read_peak_bytes_per_second": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "disk_write_peak_bytes_per_second": {
                  "type": [
                    "integer",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "MonthlyQuote": {
        "type": "object",
        "required": [
          "currency",
          "monthly_minor",
          "nominal_month_hours"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`."
          },
          "monthly_minor": {
            "type": "integer",
            "format": "int64",
            "description": "Price for a full month in minor units of `currency`."
          },
          "nominal_month_hours": {
            "type": "integer",
            "description": "Hours in the month the price assumes: 730."
          }
        }
      },
      "Network": {
        "type": "object",
        "description": "A VPC: a private network of your own.",
        "required": [
          "id",
          "name",
          "cidr",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `net_...`."
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among your VPC networks.",
            "examples": [
              "prod"
            ]
          },
          "cidr": {
            "type": "string",
            "description": "e.g. `10.0.0.0/16`."
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `af-abj`."
          },
          "zone": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `af-abj-2`."
          },
          "instance_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Instances in this VPC; null when it could not be counted."
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "NetworkList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Network"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "Operation": {
        "type": "object",
        "required": [
          "id",
          "resource_type",
          "resource_id",
          "kind",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `op_...`."
          },
          "resource_type": {
            "type": "string",
            "description": "e.g. `instance`, `volume`, `network`, `security_group`, `database`.",
            "enum": [
              "instance",
              "network",
              "subnet",
              "security_group",
              "snapshot",
              "volume",
              "ssh_access_grant",
              "relay_vm",
              "network_acl_rule",
              "public_ip",
              "port_forwarding_rule",
              "database"
            ]
          },
          "resource_id": {
            "type": "string",
            "description": "The resource the operation acts on, e.g. a `vm_…`, `db_…` or `snap_…` id. For a create, the new resource's id."
          },
          "kind": {
            "type": "string",
            "description": "What it does, e.g. `create_instance`, `stop_instance`. For a database: `create_database`, `start_database`, `stop_database`, `delete_database`, `apply_database_access_rules` (an access-rule change, attaching or detaching security groups, or the automatic re-apply after an attached group's rules changed), `change_database_password`, `reset_database_password`, `resize_database_storage`. New kinds may be added."
          },
          "status": {
            "type": "string",
            "description": "`submitting` and `submitted` while it runs; `succeeded` and `failed` are final.",
            "enum": [
              "submitting",
              "submitted",
              "succeeded",
              "failed"
            ]
          },
          "failure": {
            "$ref": "#/components/schemas/Failure",
            "description": "Why it failed, when `status` is `failed`; otherwise null."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "OptionalQuote": {
        "type": "object",
        "required": [
          "priced",
          "nominal_month_hours"
        ],
        "properties": {
          "priced": {
            "type": "boolean",
            "description": "False when no price applies; `unpriced_reason` then says why."
          },
          "unpriced_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why no price applies; null when priced."
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "`NGN` or `USD`; null when not priced."
          },
          "monthly_minor": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Price for a full month in minor units; null when not priced."
          },
          "nominal_month_hours": {
            "type": "integer",
            "description": "Hours in the month the price assumes: 730."
          }
        }
      },
      "OrderAccepted": {
        "type": "object",
        "description": "An instance is bought through an order: the initial payment is taken first (from credit, else the default card), then the instance is provisioned.",
        "required": [
          "order_id",
          "instance_id",
          "status",
          "amount_minor",
          "currency"
        ],
        "properties": {
          "order_id": {
            "type": "string",
            "description": "Follow it at `GET /public/v1/instance-orders/{order_id}` (also the `Location` header)."
          },
          "instance_id": {
            "type": "string",
            "description": "The id the instance will have."
          },
          "status": {
            "type": "string",
            "description": "The order's status now, usually `awaiting_payment`. See `InstanceOrder.status`.",
            "enum": [
              "awaiting_payment",
              "paid",
              "provisioning",
              "provisioned",
              "payment_failed",
              "failed"
            ]
          },
          "operation_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set once provisioning starts."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null for a new order; on a retry, the order's `failure_code` if it has failed since."
          },
          "amount_minor": {
            "type": "integer",
            "description": "The initial payment, in minor units (kobo or cents).",
            "format": "int64"
          },
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`.",
            "enum": [
              "NGN",
              "USD"
            ]
          }
        }
      },
      "Plan": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "vcpu",
          "memory_mb",
          "disk_gb"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The plan's id.",
            "readOnly": true
          },
          "slug": {
            "type": "string",
            "description": "Use this in `plan_slug`."
          },
          "name": {
            "type": "string",
            "description": "Its name for display."
          },
          "vcpu": {
            "type": "integer",
            "description": "Virtual CPUs.",
            "examples": [
              2
            ]
          },
          "memory_mb": {
            "type": "integer",
            "description": "Memory in MB.",
            "examples": [
              4096
            ]
          },
          "disk_gb": {
            "type": "integer",
            "description": "Root disk in GB; for a database, the smallest data disk.",
            "examples": [
              80
            ]
          },
          "price": {
            "type": [
              "object",
              "null"
            ],
            "description": "In the organization's currency; null when it cannot be priced.",
            "required": [
              "currency",
              "monthly_estimate_minor",
              "storage_floor_minor",
              "initial_payment_minor"
            ],
            "properties": {
              "currency": {
                "type": "string"
              },
              "monthly_estimate_minor": {
                "type": "integer",
                "description": "A full month running.",
                "format": "int64"
              },
              "storage_floor_minor": {
                "type": "integer",
                "description": "A full month stopped (storage only).",
                "format": "int64"
              },
              "initial_payment_minor": {
                "type": "integer",
                "description": "Taken when the instance is ordered.",
                "format": "int64"
              }
            }
          },
          "unpriced_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why `price` is null; null when priced."
          }
        }
      },
      "PlanList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plan"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "PortForwardingRule": {
        "type": "object",
        "required": [
          "id",
          "public_ip_id",
          "instance_id",
          "protocol",
          "public_port_start",
          "public_port_end",
          "private_port_start",
          "private_port_end",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `pfr_...`."
          },
          "public_ip_id": {
            "type": "string"
          },
          "instance_id": {
            "type": "string"
          },
          "instance_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The target instance's name; null when it is gone."
          },
          "protocol": {
            "type": "string",
            "description": "`tcp` or `udp`.",
            "enum": [
              "tcp",
              "udp"
            ]
          },
          "public_port_start": {
            "type": "integer"
          },
          "public_port_end": {
            "type": "integer"
          },
          "private_port_start": {
            "type": "integer"
          },
          "private_port_end": {
            "type": "integer"
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "PortForwardingRuleList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortForwardingRule"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "PricingEstimate": {
        "type": "object",
        "required": [
          "currency",
          "nominal_month_hours",
          "machines",
          "pricing_complete",
          "priced_subtotal_minor"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "description": "`NGN` or `USD`, as requested."
          },
          "nominal_month_hours": {
            "type": "integer",
            "description": "Hours in the month prices assume: 730."
          },
          "machines": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "plan_slug",
                "quantity",
                "running_hours",
                "priced"
              ],
              "properties": {
                "plan_slug": {
                  "type": "string"
                },
                "quantity": {
                  "type": "integer"
                },
                "running_hours": {
                  "type": "integer"
                },
                "priced": {
                  "type": "boolean"
                },
                "unpriced_reason": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "unit_monthly_estimate_minor": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "total_monthly_estimate_minor": {
                  "type": [
                    "integer",
                    "null"
                  ]
                }
              }
            }
          },
          "extra_storage_gb": {
            "type": "object",
            "required": [
              "requested",
              "priced"
            ],
            "properties": {
              "requested": {
                "type": "integer"
              },
              "priced": {
                "type": "boolean"
              },
              "unpriced_reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "amount_minor": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "networks": {
            "type": "object",
            "required": [
              "requested",
              "priced"
            ],
            "properties": {
              "requested": {
                "type": "integer"
              },
              "priced": {
                "type": "boolean"
              },
              "unpriced_reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "amount_minor": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "snapshot_gb": {
            "type": "object",
            "required": [
              "requested",
              "priced"
            ],
            "properties": {
              "requested": {
                "type": "integer"
              },
              "priced": {
                "type": "boolean"
              },
              "unpriced_reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "amount_minor": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "pricing_complete": {
            "type": "boolean",
            "description": "False when any line could not be priced."
          },
          "priced_subtotal_minor": {
            "type": "integer",
            "format": "int64",
            "description": "The sum of every priced line, in minor units. Lines that could not be priced are left out."
          }
        }
      },
      "PricingEstimateRequest": {
        "type": "object",
        "required": [
          "currency"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "description": "The currency to price in: `NGN` or `USD`.",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "machines": {
            "type": "array",
            "maxItems": 50,
            "description": "Instances to price: up to 50 lines, each a plan, a quantity and running hours per month.",
            "items": {
              "type": "object",
              "required": [
                "plan_slug",
                "quantity",
                "running_hours"
              ],
              "properties": {
                "plan_slug": {
                  "type": "string"
                },
                "quantity": {
                  "type": "integer",
                  "minimum": 1
                },
                "running_hours": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 730
                },
                "placement": {
                  "type": "string",
                  "enum": [
                    "standard",
                    "vpc"
                  ]
                }
              }
            }
          },
          "extra_storage_gb": {
            "type": "integer",
            "description": "Extra volume storage in GB.",
            "minimum": 0
          },
          "network_count": {
            "type": "integer",
            "description": "Number of VPC networks.",
            "minimum": 0
          },
          "snapshot_gb": {
            "type": "integer",
            "description": "Snapshot storage in GB.",
            "minimum": 0
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "Every error is an RFC 9457 problem document (`application/problem+json`).",
        "required": [
          "type",
          "title",
          "status",
          "code",
          "detail",
          "request_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI naming the problem class.",
            "format": "uri"
          },
          "title": {
            "type": "string",
            "description": "A short summary of the problem class."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code, e.g. `INSUFFICIENT_CREDIT`. Branch on this, never on `title` or `detail`."
          },
          "detail": {
            "type": "string",
            "description": "What went wrong in this case and what to do next, in plain language. Safe to show to your users. Its wording may change: branch on `code`."
          },
          "request_id": {
            "type": "string",
            "description": "This request's id (also in the `X-Request-Id` response header). Quote it to support."
          },
          "errors": {
            "type": "array",
            "description": "Present on `VALIDATION_FAILED`: one entry per invalid field.",
            "items": {
              "type": "object",
              "required": [
                "field",
                "code",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string",
                  "description": "The request field, e.g. `plan_slug`."
                },
                "code": {
                  "type": "string",
                  "description": "Stable code for this field's problem, e.g. `REQUIRED`."
                },
                "message": {
                  "type": "string",
                  "description": "What the field must be."
                }
              }
            }
          }
        }
      },
      "AttachPublicIPRequest": {
        "type": "object",
        "required": [
          "instance_id"
        ],
        "properties": {
          "instance_id": {
            "type": "string",
            "description": "An instance in the address's private network.",
            "examples": [
              "vm_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          }
        }
      },
      "PublicIP": {
        "type": "object",
        "required": [
          "id",
          "network_id",
          "purpose",
          "desired_state",
          "observed_state",
          "in_sync"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `pip_...`."
          },
          "network_id": {
            "type": "string"
          },
          "network_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The VPC's name."
          },
          "purpose": {
            "type": "string",
            "description": "`static_nat` maps every port to one instance; `port_forwarding` carries per-port rules.",
            "enum": [
              "static_nat",
              "port_forwarding",
              "load_balancer"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "The public IPv4 address; null until allocated."
          },
          "instance_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "static_nat: the instance it maps to; null while it is detached (still yours, and billed once)."
          },
          "instance_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The mapped instance's name; null when none."
          },
          "region": {
            "type": [
              "string",
              "null"
            ]
          },
          "zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "in_sync": {
            "type": "boolean",
            "description": "False while an attach or detach has not reached the address yet."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "PublicIPList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicIP"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "PutSnapshotScheduleRequest": {
        "type": "object",
        "required": [
          "frequency"
        ],
        "properties": {
          "frequency": {
            "type": "string",
            "description": "How often: `daily`, `weekly` or `monthly`.",
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ]
          },
          "retention_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 168,
            "default": 7,
            "description": "How many successful automatic snapshots to keep, 1 to 168; older ones are deleted. Defaults to 7."
          },
          "enabled": {
            "type": "boolean",
            "default": true,
            "description": "False pauses the schedule without forgetting it. Defaults to true."
          }
        }
      },
      "RebuildRequest": {
        "type": "object",
        "properties": {
          "image_slug": {
            "type": "string",
            "description": "The image to install, from `GET /public/v1/images`. Leave out to reinstall the current image.",
            "examples": [
              "ubuntu-24-04"
            ]
          }
        }
      },
      "Region": {
        "type": "object",
        "required": [
          "code",
          "name",
          "placements"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "e.g. `af-abj`."
          },
          "name": {
            "type": "string",
            "description": "Its name for display."
          },
          "placements": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "kind",
                "zone",
                "available"
              ],
              "properties": {
                "kind": {
                  "type": "string",
                  "description": "`standard` instances or `vpc` networks.",
                  "enum": [
                    "standard",
                    "vpc"
                  ]
                },
                "zone": {
                  "type": "string"
                },
                "available": {
                  "type": "boolean"
                },
                "unavailable_reason": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "private_network_cidr": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The range of the zone's private database network, e.g. `10.250.0.0/20`, when instances there can add a private network interface (`POST /public/v1/instances/{instance_id}/private-network`); null otherwise, and in every VPC zone. Allow this range nowhere in the security group of an instance with that interface.",
                  "examples": [
                    "10.250.0.0/20"
                  ]
                }
              }
            }
          }
        }
      },
      "RegionList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Region"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "RenameRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The new name: 1 to 255 characters of lowercase letters a-z, digits 0-9 and hyphens (-), starting and ending with a letter or digit, unique among your instances. Anything else is refused with 422 INVALID_INSTANCE_NAME.",
            "minLength": 1,
            "maxLength": 255,
            "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
            "examples": [
              "web-2"
            ]
          }
        }
      },
      "ReplaceDatabaseAccessRulesRequest": {
        "type": "object",
        "required": [
          "rules"
        ],
        "properties": {
          "rules": {
            "type": "array",
            "maxItems": 50,
            "description": "The complete new allow-list, at most 50 rules with no range twice. `[]` removes every rule.",
            "items": {
              "$ref": "#/components/schemas/DatabaseAccessRuleRequest"
            }
          }
        }
      },
      "ReplaceSecurityGroupRulesRequest": {
        "type": "object",
        "required": [
          "rules"
        ],
        "properties": {
          "rules": {
            "type": "array",
            "description": "The complete new rule list; at least one rule. It replaces every existing rule.",
            "items": {
              "$ref": "#/components/schemas/SecurityGroupRule"
            }
          }
        }
      },
      "ChangeSSHKeyRequest": {
        "type": "object",
        "required": [
          "ssh_key_id"
        ],
        "properties": {
          "ssh_key_id": {
            "type": "string",
            "description": "The SSH key the instance should accept from now on, from `GET /public/v1/ssh-keys`. It replaces the instance's current key."
          }
        }
      },
      "ResizeRequest": {
        "type": "object",
        "required": [
          "plan_slug"
        ],
        "properties": {
          "plan_slug": {
            "type": "string",
            "description": "A bigger plan than the instance's current one, from `GET /public/v1/plans`. Instances only grow."
          }
        }
      },
      "ResizeVolumeRequest": {
        "type": "object",
        "required": [
          "disk_offering_slug"
        ],
        "properties": {
          "disk_offering_slug": {
            "type": "string",
            "description": "The volume type after the resize, from `GET /public/v1/disk-offerings`."
          },
          "size_gb": {
            "type": "integer",
            "description": "The new size in GB, for a custom-size offering: larger than the current size. Volumes only grow."
          }
        }
      },
      "RestoreRequest": {
        "type": "object",
        "required": [
          "snapshot_id",
          "confirm_name"
        ],
        "properties": {
          "snapshot_id": {
            "type": "string",
            "description": "A snapshot of this instance's root disk.",
            "examples": [
              "snap_06gk3x9tq7m2v8r4y1c5d0zp8w"
            ]
          },
          "confirm_name": {
            "type": "string",
            "description": "The instance's current name, exactly, to confirm: everything written since the snapshot is lost.",
            "examples": [
              "web-1"
            ]
          }
        }
      },
      "RestoreSnapshotRequest": {
        "type": "object",
        "required": [
          "name",
          "disk_offering_slug"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the new volume, 1 to 255 characters.",
            "examples": [
              "data-restored"
            ]
          },
          "disk_offering_slug": {
            "type": "string",
            "description": "The new volume's type, from `GET /public/v1/disk-offerings`."
          },
          "size_gb": {
            "type": "integer",
            "description": "For a custom-size offering: at least the snapshot's size in GB."
          }
        }
      },
      "SSHAccessGrant": {
        "type": "object",
        "required": [
          "id",
          "instance_id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `sshg_...`."
          },
          "instance_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`pending` while the port is being opened, `active` once you can connect, then `revoking`, `revoked`, `expired` or `failed`.",
            "enum": [
              "pending",
              "active",
              "revoking",
              "revoked",
              "expired",
              "failed"
            ]
          },
          "host": {
            "type": [
              "string",
              "null"
            ],
            "description": "Connect here once `active`."
          },
          "port": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The port to connect to once `active`, usually 22."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the port closes by itself, 15 minutes after it opened."
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was revoked; null otherwise."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "SSHKey": {
        "type": "object",
        "required": [
          "id",
          "name",
          "fingerprint",
          "public_key"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `sshk_...`."
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among your SSH keys."
          },
          "fingerprint": {
            "type": "string",
            "description": "The key's SHA256 fingerprint."
          },
          "public_key": {
            "type": "string",
            "description": "The OpenSSH public key."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "SSHKeyList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SSHKey"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "SecurityGroup": {
        "type": "object",
        "description": "A reusable firewall for standard instances.",
        "required": [
          "id",
          "name",
          "rules",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `sg_...`."
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among your live security groups. The organization's default group is called `default`.",
            "examples": [
              "web"
            ]
          },
          "rules": {
            "type": "array",
            "description": "Its rules. Inbound traffic no rule allows is dropped.",
            "items": {
              "$ref": "#/components/schemas/SecurityGroupRule"
            }
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "SecurityGroupList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SecurityGroup"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "SecurityGroupRule": {
        "type": "object",
        "required": [
          "direction",
          "protocol",
          "cidr"
        ],
        "properties": {
          "direction": {
            "type": "string",
            "description": "`ingress` (into the instance) or `egress` (out of it).",
            "enum": [
              "ingress",
              "egress"
            ]
          },
          "protocol": {
            "type": "string",
            "description": "`tcp`, `udp`, `icmp` or `all`.",
            "enum": [
              "tcp",
              "udp",
              "icmp",
              "all"
            ]
          },
          "port_range": {
            "type": "string",
            "description": "For `tcp`/`udp`: one port (`22`) or an inclusive range (`8000-8100`). Empty or left out for `icmp` and `all`, meaning every port.",
            "examples": [
              "22"
            ]
          },
          "cidr": {
            "type": "string",
            "description": "One IPv4 CIDR: the source for `ingress`, the destination for `egress`, e.g. `203.0.113.4/32`. Avoid `0.0.0.0/0` on ingress where you can: it blocks private database network interfaces on instances using the group.",
            "examples": [
              "203.0.113.4/32"
            ]
          }
        }
      },
      "Snapshot": {
        "type": "object",
        "required": [
          "id",
          "name",
          "trigger",
          "size_bytes",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `snap_...`."
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among its source's snapshots.",
            "examples": [
              "pre-upgrade"
            ]
          },
          "instance_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set for a snapshot of an instance's root disk."
          },
          "source_instance_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The source instance's name; null when it is gone or not an instance snapshot."
          },
          "volume_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set for a snapshot of a volume. Exactly one of instance_id, volume_id and database_id is set."
          },
          "volume_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The source volume's name; null when it is gone or not a volume snapshot."
          },
          "database_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set for a snapshot of a managed database's data disk. Exactly one of `instance_id`, `volume_id` and `database_id` is set."
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "description": "The source's region, e.g. `af-abj`."
          },
          "trigger": {
            "type": "string",
            "description": "`automatic` when taken by a snapshot schedule.",
            "enum": [
              "manual",
              "automatic"
            ]
          },
          "size_bytes": {
            "type": "integer",
            "description": "Storage used; 0 until complete.",
            "format": "int64"
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the snapshot finished; null until then."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "SnapshotList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Snapshot"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "SnapshotSchedule": {
        "type": "object",
        "required": [
          "frequency",
          "retention_count",
          "enabled"
        ],
        "properties": {
          "instance_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The instance whose root disk is snapshotted; null for a volume's schedule."
          },
          "volume_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The volume snapshotted; null for an instance's schedule."
          },
          "frequency": {
            "type": "string",
            "description": "`daily`, `weekly` or `monthly`.",
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ]
          },
          "retention_count": {
            "type": "integer",
            "description": "Successful copies kept; older ones are deleted.",
            "minimum": 1,
            "maximum": 168
          },
          "enabled": {
            "type": "boolean",
            "description": "False while paused."
          },
          "next_run_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the next automatic snapshot is due; null while paused."
          }
        }
      },
      "Subnet": {
        "type": "object",
        "required": [
          "id",
          "network_id",
          "name",
          "cidr",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `snet_...`."
          },
          "network_id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Its name.",
            "examples": [
              "app"
            ]
          },
          "cidr": {
            "type": "string",
            "description": "Inside the VPC's CIDR."
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `af-abj`."
          },
          "zone": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `af-abj-2`."
          },
          "instance_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Instances in this subnet; null when they could not be counted."
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "SubnetList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Subnet"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "UsageByResource": {
        "type": "object",
        "required": [
          "currency",
          "period_start",
          "period_end",
          "data"
        ],
        "properties": {
          "currency": {
            "type": "string"
          },
          "period_start": {
            "type": "string"
          },
          "period_end": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "resource_id": {
                  "type": "string"
                },
                "resource_name": {
                  "type": "string"
                },
                "resource_kind": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "days_active": {
                  "type": "integer"
                },
                "window_days": {
                  "type": "integer"
                },
                "rate_unit": {
                  "type": "string"
                },
                "rate_unit_price_micros": {
                  "type": "integer",
                  "format": "int64"
                },
                "cost_minor": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            }
          }
        }
      },
      "CreateCreditPurchaseRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "amount_minor"
        ],
        "properties": {
          "amount_minor": {
            "type": "integer",
            "format": "int64",
            "description": "How much credit to buy, in minor units of your organization's currency: kobo for NGN, cents for USD."
          }
        }
      },
      "Receipt": {
        "type": "object",
        "description": "A receipt for money that moved on your account. Amounts are integers in minor units of `currency`.",
        "required": [
          "id",
          "number",
          "kind",
          "issuer_name",
          "currency",
          "amount_minor",
          "issued_at",
          "occurred_at",
          "description",
          "billed_to",
          "facts",
          "verification",
          "transaction_id",
          "pdf_bytes"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `rcp_...`."
          },
          "number": {
            "type": "string",
            "description": "`PTD-RCT-<year>-<number>`, sequential within the year."
          },
          "kind": {
            "type": "string",
            "enum": [
              "payment",
              "invoice_payment",
              "credit_purchase",
              "wallet_debit",
              "refund"
            ],
            "description": "`payment` a card payment, `invoice_payment` an invoice paid by card or from credit, `credit_purchase` a top-up, `wallet_debit` credit taken for a new resource, `refund` money returned to your credit."
          },
          "issuer_name": {
            "type": "string",
            "description": "The Pantech company that issued it: `Pantech Dynamics, Inc.` for USD payments, `Pantech Dynamics Ltd` for NGN payments."
          },
          "currency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "amount_minor": {
            "type": "integer",
            "format": "int64"
          },
          "issued_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the receipt was issued."
          },
          "occurred_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the money moved."
          },
          "description": {
            "type": "string",
            "description": "What it was for, e.g. `Account credit top-up`."
          },
          "billed_to": {
            "type": "string",
            "description": "Your organization, as printed on the receipt."
          },
          "facts": {
            "type": "array",
            "description": "The details printed on the receipt, e.g. the payment method (`Visa •••• 4242`) and the date.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "value"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              }
            }
          },
          "verification": {
            "type": "string",
            "description": "The code printed on the receipt, which Pantech uses to confirm a copy is genuine."
          },
          "transaction_id": {
            "type": "string",
            "description": "The account transaction the receipt is for, e.g. `ltx_...`."
          },
          "pdf_bytes": {
            "type": "integer",
            "description": "The size of the PDF."
          }
        }
      },
      "ReceiptList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Receipt"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "CreditPurchase": {
        "type": "object",
        "description": "One credit top-up.",
        "required": [
          "id",
          "status",
          "amount_minor",
          "currency",
          "method",
          "provider",
          "checkout_url",
          "checkout_expires_at",
          "failure_code",
          "settled_at",
          "created_at",
          "receipt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `cpr_...`."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "settled",
              "failed",
              "expired",
              "refunded",
              "charged_back"
            ],
            "description": "`pending` until paid; `settled` once the credit is in your balance."
          },
          "amount_minor": {
            "type": "integer",
            "format": "int64",
            "description": "The credit bought, in minor units of `currency`."
          },
          "currency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "checkout",
              "saved_card",
              "bank_transfer"
            ],
            "description": "`checkout` for every purchase made through the API. Purchases made in the console may show another method."
          },
          "provider": {
            "type": "string",
            "description": "An identifier for the payment processor that takes the payment. Treat it as an opaque label: values can be added."
          },
          "checkout_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The provider's hosted payment page. Present only while the purchase is `pending` and can still be paid."
          },
          "checkout_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the payment link stops working, if the provider sets a time."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the payment failed, when `status` is `failed`."
          },
          "settled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the credit was added; null until then."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "receipt": {
            "type": [
              "object",
              "null"
            ],
            "description": "The receipt, once the purchase has settled and the receipt is issued (usually within a minute); null until then. Fetch it with `GET /public/v1/billing/receipts/{receipt_id}`.",
            "required": [
              "id",
              "number"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "e.g. `rcp_...`."
              },
              "number": {
                "type": "string",
                "description": "e.g. `PTD-RCT-2026-000123`."
              }
            }
          }
        }
      },
      "CreditOutlook": {
        "type": "object",
        "description": "Credit against the estimated next invoice. Amounts are integers in minor units of `currency`.",
        "required": [
          "currency",
          "available_minor",
          "pending_minor",
          "prepaid_minor",
          "estimated_next_invoice_minor",
          "next_invoice_at",
          "standing",
          "has_payment_method"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD"
            ]
          },
          "available_minor": {
            "type": "integer",
            "format": "int64",
            "description": "Credit you can spend now."
          },
          "pending_minor": {
            "type": "integer",
            "format": "int64",
            "description": "Credit purchases that haven't settled yet. Not spendable until they do."
          },
          "prepaid_minor": {
            "type": "integer",
            "format": "int64",
            "description": "Initial payments for new instances that haven't been used yet. They count toward your next invoice before credit does."
          },
          "estimated_next_invoice_minor": {
            "type": "integer",
            "format": "int64",
            "description": "An estimate of your next invoice, including VAT."
          },
          "next_invoice_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the current billing period closes and the invoice is issued."
          },
          "standing": {
            "type": "string",
            "description": "`covered` when credit and prepaid instance payments cover the estimate, `low` when they don't, `empty` when no credit is left. Buy credit with `POST /public/v1/billing/credit/purchases`.",
            "enum": [
              "covered",
              "low",
              "empty"
            ]
          },
          "has_payment_method": {
            "type": "boolean",
            "description": "Whether a default payment method will be charged for anything credit doesn't cover."
          }
        }
      },
      "UsageSummary": {
        "type": "object",
        "required": [
          "totals",
          "entries"
        ],
        "properties": {
          "window_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Start of the measured window; null when nothing was measured."
          },
          "window_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "End of the measured window; null when nothing was measured."
          },
          "totals": {
            "type": "object",
            "properties": {
              "running_hours": {
                "type": "number"
              },
              "storage_gb_hours": {
                "type": "number"
              },
              "allocated_memory_mb_hours": {
                "type": "number"
              },
              "network_bytes_sent": {
                "type": "number"
              },
              "network_bytes_received": {
                "type": "number"
              }
            }
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "resource_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "usage_type": {
                  "type": "integer"
                },
                "usage": {
                  "type": "string"
                },
                "period_start": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "period_end": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "Volume": {
        "type": "object",
        "required": [
          "id",
          "name",
          "size_gb",
          "disk_offering_slug",
          "desired_state",
          "observed_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `vol_...`."
          },
          "name": {
            "type": "string",
            "description": "Its name.",
            "examples": [
              "data"
            ]
          },
          "size_gb": {
            "type": "integer",
            "description": "Its size in GB.",
            "examples": [
              100
            ]
          },
          "disk_offering_slug": {
            "type": "string",
            "description": "See `GET /public/v1/disk-offerings`."
          },
          "storage_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "The storage class, e.g. `shared`; null when not stated."
          },
          "region": {
            "type": [
              "string",
              "null"
            ]
          },
          "zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "attached_instance_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The instance it is attached to; null when detached."
          },
          "attached_instance_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "That instance's name; null when detached."
          },
          "desired_instance_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where an attach in progress is moving it."
          },
          "mount_point": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where it is mounted, when mounted at create; null otherwise."
          },
          "source_snapshot_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when restored from a snapshot."
          },
          "monthly_cost": {
            "type": [
              "object",
              "null"
            ],
            "description": "What it costs per month at its size; null when it cannot be priced.",
            "required": [
              "currency",
              "amount_minor"
            ],
            "properties": {
              "currency": {
                "type": "string"
              },
              "amount_minor": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "desired_state": {
            "type": "string",
            "description": "What you asked for: `present`, or `deleted` once you deleted it.",
            "enum": [
              "present",
              "deleted"
            ]
          },
          "observed_state": {
            "type": "string",
            "description": "What the platform last observed: `pending` and `provisioning` while it is being created, `active` once ready, `deleting`/`deleted` on the way out, `failed` if it could not be made, `unknown` when it could not be checked.",
            "enum": [
              "pending",
              "provisioning",
              "active",
              "deleting",
              "deleted",
              "failed",
              "unknown"
            ]
          },
          "encryption": {
            "type": "object",
            "description": "What the platform can truthfully say about this volume's encryption. `status` is `none` for a plain volume, `requested` when you asked for encryption at creation and the disk has not been formatted yet, and `encrypted` once the platform has confirmed the disk was formatted with a key from the volume key service. `encrypted` is set only by the platform, never from a claim.",
            "required": [
              "status"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "none",
                  "requested",
                  "encrypted"
                ]
              }
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC).",
            "readOnly": true
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC).",
            "readOnly": true
          }
        }
      },
      "VolumeList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Volume"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "Webhook": {
        "type": "object",
        "description": "A URL Pantech sends your organization's events to.",
        "required": [
          "id",
          "url",
          "description",
          "events",
          "enabled",
          "disabled_reason",
          "failing_since",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `whk_...`."
          },
          "url": {
            "type": "string",
            "description": "Where events are sent: an `https` URL on the public internet.",
            "examples": [
              "https://example.com/hooks/pantech"
            ]
          },
          "description": {
            "type": "string",
            "description": "Your note about it; may be empty."
          },
          "events": {
            "type": "array",
            "description": "What it subscribes to: event types, `<resource>.*`, or `*`.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "instance.*",
                "invoice.paid"
              ]
            ]
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether events are sent to it."
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it is disabled: `disabled_by_user`, or `failing` after three days of failed deliveries. Null while enabled.",
            "enum": [
              "disabled_by_user",
              "failing",
              null
            ]
          },
          "failing_since": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When its deliveries started failing with no success since (RFC 3339, UTC); null while they succeed."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was created (RFC 3339, UTC)."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it last changed (RFC 3339, UTC)."
          }
        }
      },
      "WebhookWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The signing secret (`whsec_…`). Shown only in this response; null when a create is replayed."
              }
            }
          }
        ]
      },
      "WebhookList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "An `https` URL on the public internet, at most 2,048 characters, with no user name or password.",
            "examples": [
              "https://example.com/hooks/pantech"
            ]
          },
          "description": {
            "type": "string",
            "description": "A note for yourself, at most 255 characters.",
            "examples": [
              "Production alerts"
            ]
          },
          "events": {
            "type": "array",
            "description": "1 to 100 entries: event types from `GET /webhook-event-types`, `<resource>.*`, or `*`.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "instance.*",
                "invoice.paid"
              ]
            ]
          }
        }
      },
      "UpdateWebhookRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "A new `https` URL."
          },
          "description": {
            "type": "string",
            "description": "A new note, at most 255 characters."
          },
          "events": {
            "type": "array",
            "description": "The new subscriptions, replacing the old ones.",
            "items": {
              "type": "string"
            }
          },
          "enabled": {
            "type": "boolean",
            "description": "`false` stops deliveries; `true` resumes them and clears the failure history."
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "description": "One event sent, or waiting to be sent, to one webhook.",
        "required": [
          "id",
          "webhook_id",
          "event_id",
          "event_type",
          "status",
          "attempts",
          "next_attempt_at",
          "last_attempt_at",
          "last_status_code",
          "last_error",
          "last_response",
          "last_duration_ms",
          "delivered_at",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "e.g. `whd_...`."
          },
          "webhook_id": {
            "type": "string",
            "description": "The webhook it is for."
          },
          "event_id": {
            "type": "string",
            "description": "The event's `id`, the same in every delivery of it: deduplicate on it."
          },
          "event_type": {
            "type": "string",
            "description": "e.g. `instance.created`."
          },
          "status": {
            "type": "string",
            "description": "`pending` until it succeeds, fails eight times, or is cancelled because the webhook was disabled or deleted.",
            "enum": [
              "pending",
              "succeeded",
              "failed",
              "canceled"
            ]
          },
          "attempts": {
            "type": "integer",
            "description": "How many times it has been sent."
          },
          "next_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it is next sent, while `pending`."
          },
          "last_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was last sent."
          },
          "last_status_code": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The HTTP status your endpoint last answered; null if it did not answer."
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the last attempt failed: `http_<status>`, `timeout`, `connection_failed`, `dns_failed`, `tls_failed`, `blocked_address` (the URL resolved to an address that is not on the public internet), `invalid_url`, `endpoint_disabled` or `endpoint_deleted`."
          },
          "last_response": {
            "type": [
              "string",
              "null"
            ],
            "description": "The first 1,024 characters of your endpoint's last response body."
          },
          "last_duration_ms": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How long the last attempt took, in milliseconds."
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it succeeded."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the event was queued for this webhook."
          }
        }
      },
      "WebhookDeliveryDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookDelivery"
          },
          {
            "type": "object",
            "required": [
              "payload"
            ],
            "properties": {
              "payload": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        ]
      },
      "WebhookDeliveryList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "description": "The body of every delivery. An infrastructure event's `data` names the resource and the change: `resource_type`, `resource_id`, `operation_id`, `action`, `status` (`succeeded` or `failed`) and, on failure, `error` with the same safe `code` and `message` the operations API returns. Read the resource through the API for more. A billing event's `data` carries its amounts in minor units.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The event's id (`evt_…`). Deduplicate on it."
          },
          "type": {
            "type": "string",
            "description": "e.g. `instance.created`, `invoice.paid`, `webhook.test`."
          },
          "api_version": {
            "type": "string",
            "description": "The shape of this body, as a date: `2026-10-22`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (RFC 3339, UTC)."
          },
          "organization_id": {
            "type": "string",
            "description": "Your organization."
          },
          "project_id": {
            "type": "string",
            "description": "The project (`acc_…`) the resource is in."
          },
          "data": {
            "type": "object",
            "description": "What happened; depends on `type`."
          }
        }
      },
      "WebhookEventType": {
        "type": "object",
        "required": [
          "type",
          "resource",
          "description"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "e.g. `instance.created`."
          },
          "resource": {
            "type": "string",
            "description": "What it is about, for `<resource>.*` subscriptions."
          },
          "description": {
            "type": "string",
            "description": "What it means."
          }
        }
      },
      "WebhookEventTypeList": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: this list is returned whole."
          }
        }
      }
    }
  }
}
