# VpsAgent — Full Reference

{
  "openapi": "3.1.0",
  "info": {
    "title": "VpsAgent",
    "version": "0.1.0",
    "summary": "Disposable VPS instances for AI agents — paid via x402 (USDC on Base).",
    "description": "Two product lines: ephemeral sandboxes (1h / 6h / 24h, $0.50–$5) for code execution, CI runs, browser automation; persistent servers (small / medium / large, 30-day or 365-day, $9.99–$359.99) for hosting agents and services. Pay-on-success: USDC settles only when the box is reachable on TCP :22. Failed provisions never settle — the EIP-3009 authorization expires unused, agent pays nothing. No signup, no API keys, machine-to-machine.",
    "license": {
      "name": "Proprietary"
    },
    "contact": {
      "name": "VpsAgent"
    }
  },
  "servers": [
    {
      "url": "https://vpsagent.fly.dev"
    }
  ],
  "x-x402": {
    "scheme": "exact",
    "network": "base",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x8eCbd65228930060363C70854da7D37D57ffC358"
  },
  "paths": {
    "/catalog": {
      "get": {
        "operationId": "listCatalog",
        "summary": "List rentable SKUs across both tracks.",
        "description": "Live storefront. Returns nine SKUs across two tracks (sandbox + server) with prices, spec floors, durations, and Phase-1 availability flags. Paid discovery: 0.01 USDC per call, settled inline. The dust price exists to register the resource in CDP Bazaar's discovery index.",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Payment-Response": {
                "description": "Base64-encoded `{tx, network}` of the on-chain settlement.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogList"
                }
              }
            }
          },
          "402": {
            "description": "Payment required. Body is x402 PaymentRequirements priced at 0.01 USDC.",
            "headers": {
              "X-Payment-Required": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentChallenge"
                }
              }
            }
          }
        }
      }
    },
    "/rent": {
      "post": {
        "operationId": "rent",
        "summary": "Provision a VPS instance.",
        "description": "Submit a SKU; receive a 402 with priced paymentRequirements; sign an EIP-3009 transferWithAuthorization for the SKU price; resubmit with the X-Payment header. We verify (NOT settle), provision the box upstream, and persist the rental. Worker calls /settle only when the box is reachable on TCP :22 — typically 3–5 minutes for server-track SKUs. If the box never comes up, settle is never called and the EIP-3009 authorization dies via validBefore. Agent paid nothing.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RentBody"
              },
              "examples": {
                "small": {
                  "value": {
                    "sku": "server_small_1mo"
                  }
                },
                "large_with_region": {
                  "value": {
                    "sku": "server_large_1mo",
                    "region": "EU"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provisioned. Settle pending — the worker will charge once the box is up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RentalCreated"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body. See the response detail for which field failed."
          },
          "402": {
            "description": "Payment required (or payment invalid)."
          },
          "503": {
            "description": "SKU advertised but not yet routable in Phase 1, or upstream provider unavailable."
          }
        }
      }
    },
    "/rentals/{rental_id}": {
      "get": {
        "operationId": "getRental",
        "summary": "Public lifecycle snapshot.",
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RentalStatus"
                }
              }
            }
          },
          "404": {
            "description": "Rental not found."
          }
        }
      }
    },
    "/rentals/{rental_id}/renew": {
      "post": {
        "operationId": "renew",
        "summary": "Extend a rental's expires_at.",
        "description": "Token-gated. Stack cap periods ∈ [1, 12]. Same flow as /rent: 402 → sign → resubmit → verify (no settle yet). Server-track renewals require a manual ops touch on the upstream provider's panel; the worker waits for the cancel-revoke and only then settles + re-cancels at the new expires_at. Crucially: expires_at does NOT change until the renewal fully settles — if the renewal never completes, the original expires_at remains in force and the rental is destroyed at the original cancelDate. Agent paid nothing.",
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "root_token from POST /rent."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenewBody"
              },
              "examples": {
                "default": {
                  "value": {
                    "periods": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Renewal verified, settle pending.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenewalCreated"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid token."
          },
          "402": {
            "description": "Payment required (or invalid)."
          },
          "404": {
            "description": "Rental not found."
          },
          "409": {
            "description": "Rental not in 'active' status."
          }
        }
      }
    },
    "/instance/{rental_id}": {
      "get": {
        "operationId": "getInstance",
        "summary": "Live status: ipv4, running flag, expires_at.",
        "description": "Token-gated. Use this to poll for `running == true` after /rent.",
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceStatus"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid token."
          },
          "404": {
            "description": "Rental not found."
          },
          "502": {
            "description": "Upstream provider unreachable; last-known fields returned."
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "operationId": "healthz",
        "summary": "Liveness probe.",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CatalogList": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "sku": {
              "type": "string",
              "enum": [
                "sandbox_1h",
                "sandbox_6h",
                "sandbox_24h",
                "server_small_1mo",
                "server_small_12mo",
                "server_medium_1mo",
                "server_medium_12mo",
                "server_large_1mo",
                "server_large_12mo"
              ]
            },
            "track": {
              "type": "string",
              "enum": [
                "sandbox",
                "server"
              ]
            },
            "price_usdc": {
              "type": "number"
            },
            "duration_minutes": {
              "type": "integer"
            },
            "spec_floor": {
              "type": "object",
              "properties": {
                "vcpu": {
                  "type": "integer"
                },
                "memory_mb": {
                  "type": "integer"
                }
              }
            },
            "available": {
              "type": "boolean"
            },
            "description": {
              "type": "string"
            }
          }
        }
      },
      "PaymentChallenge": {
        "type": "object",
        "properties": {
          "x402Version": {
            "type": "integer",
            "const": 1
          },
          "accepts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentRequirements"
            }
          },
          "error": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "PaymentRequirements": {
        "type": "object",
        "properties": {
          "scheme": {
            "type": "string",
            "const": "exact"
          },
          "network": {
            "type": "string",
            "example": "base"
          },
          "maxAmountRequired": {
            "type": "string",
            "description": "USDC base units (6 decimals)."
          },
          "amount": {
            "type": "string",
            "description": "Same as maxAmountRequired (CDP requires both fields)."
          },
          "resource": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string"
          },
          "mimeType": {
            "type": "string",
            "const": "application/json"
          },
          "payTo": {
            "type": "string"
          },
          "maxTimeoutSeconds": {
            "type": "integer"
          },
          "asset": {
            "type": "string"
          },
          "extra": {
            "type": "object"
          },
          "outputSchema": {
            "type": "object"
          }
        }
      },
      "RentBody": {
        "type": "object",
        "required": [
          "sku"
        ],
        "properties": {
          "sku": {
            "type": "string",
            "enum": [
              "sandbox_1h",
              "sandbox_6h",
              "sandbox_24h",
              "server_small_1mo",
              "server_small_12mo",
              "server_medium_1mo",
              "server_medium_12mo",
              "server_large_1mo",
              "server_large_12mo"
            ]
          },
          "region": {
            "type": "string",
            "description": "Optional region preference; provider picks default if absent."
          }
        }
      },
      "RentalCreated": {
        "type": "object",
        "properties": {
          "rental_id": {
            "type": "string",
            "format": "uuid"
          },
          "sku": {
            "type": "string",
            "enum": [
              "sandbox_1h",
              "sandbox_6h",
              "sandbox_24h",
              "server_small_1mo",
              "server_small_12mo",
              "server_medium_1mo",
              "server_medium_12mo",
              "server_large_1mo",
              "server_large_12mo"
            ]
          },
          "ipv4": {
            "type": [
              "string",
              "null"
            ],
            "description": "Box IPv4. May be null at first; poll GET /instance/{id}."
          },
          "expires_at": {
            "type": "integer",
            "description": "Unix ms."
          },
          "root_token": {
            "type": "string",
            "description": "Bearer for GET /instance/{id} and POST /rentals/{id}/renew. Treat as a credential."
          },
          "root_user": {
            "type": "string",
            "const": "root",
            "description": "SSH username."
          },
          "root_password": {
            "type": "string",
            "description": "SSH password — set via cloud-init at first boot. Re-fetchable via GET /instance/{id}?token=…"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_settlement"
            ]
          },
          "note": {
            "type": "string"
          }
        }
      },
      "RentalStatus": {
        "type": "object",
        "properties": {
          "rental_id": {
            "type": "string",
            "format": "uuid"
          },
          "sku": {
            "type": "string",
            "enum": [
              "sandbox_1h",
              "sandbox_6h",
              "sandbox_24h",
              "server_small_1mo",
              "server_small_12mo",
              "server_medium_1mo",
              "server_medium_12mo",
              "server_large_1mo",
              "server_large_12mo"
            ]
          },
          "track": {
            "type": "string",
            "enum": [
              "sandbox",
              "server"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_settlement",
              "active",
              "renewing",
              "expired"
            ]
          },
          "created_at": {
            "type": "integer"
          },
          "expires_at": {
            "type": "integer"
          },
          "grace_until": {
            "type": [
              "integer",
              "null"
            ]
          },
          "settle_tx_hash": {
            "type": [
              "string",
              "null"
            ]
          },
          "renewal_count": {
            "type": "integer"
          },
          "last_renewal_tx_hash": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "RenewBody": {
        "type": "object",
        "properties": {
          "periods": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 1
          }
        }
      },
      "RenewalCreated": {
        "type": "object",
        "properties": {
          "rental_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "renewing"
            ]
          },
          "current_expires_at": {
            "type": "integer"
          },
          "predicted_expires_at": {
            "type": "integer"
          },
          "manual_step": {
            "type": "string"
          }
        }
      },
      "InstanceStatus": {
        "type": "object",
        "properties": {
          "rental_id": {
            "type": "string",
            "format": "uuid"
          },
          "ipv4": {
            "type": [
              "string",
              "null"
            ]
          },
          "running": {
            "type": "boolean"
          },
          "expires_at": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_settlement",
              "active",
              "renewing",
              "expired"
            ]
          },
          "root_user": {
            "type": "string",
            "const": "root"
          },
          "root_password": {
            "type": "string"
          },
          "note": {
            "type": "string"
          }
        }
      }
    }
  }
}
