{"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"}}}}}}