{"openapi":"3.0.3","info":{"title":"Otwa Cloud API","version":"1.5.0","description":"REST API for Otwa Cloud — deploy and manage cloud servers, retrieve credentials, attach add-ons with prorated billing, and automate your infrastructure programmatically.","contact":{"name":"Otwa Cloud Support","email":"support@otwa.cloud","url":"https://otwa.cloud/support"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://otwa.cloud/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key (otwa_...)","description":"Generate an API key from your dashboard at https://otwa.cloud/dashboard/api"}},"schemas":{"Error":{"type":"object","properties":{"message":{"type":"string","example":"Unauthorized"},"statusCode":{"type":"integer","example":401}}},"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"firstName":{"type":"string"},"lastName":{"type":"string"},"balance":{"type":"string","example":"50.00"},"tier":{"type":"string","enum":["standard","pro","enterprise"]},"createdAt":{"type":"string","format":"date-time"}}},"Product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"vcpu":{"type":"integer","example":2},"ramMb":{"type":"integer","example":4096},"diskGb":{"type":"integer","example":50},"bandwidthGb":{"type":"integer","example":1000},"monthlyPrice":{"type":"string","example":"10.00"},"region":{"type":"string","example":"OTWA IST"}}},"IpEntry":{"type":"object","properties":{"ip":{"type":"string","example":"198.51.100.11"},"gateway":{"type":"string","example":"198.51.100.1"},"netmask":{"type":"string","example":"255.255.255.0"},"cidr":{"type":"string","example":"198.51.100.0/24"},"region":{"type":"string","example":"OTWA IST"}}},"ServerSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","example":"prod-1"},"hostname":{"type":"string","example":"srv1.example.com"},"status":{"type":"string","enum":["pending","provisioning","running","stopped","suspended","terminated"]},"ipAddress":{"type":"string","example":"198.51.100.10","nullable":true},"os":{"type":"string","example":"ubuntu-2404"},"region":{"type":"string","example":"OTWA IST"},"vcpu":{"type":"integer","example":2},"ramMb":{"type":"integer","example":4096},"diskGb":{"type":"integer","example":50},"bandwidthGb":{"type":"integer","example":1000},"additionalIps":{"type":"array","items":{"$ref":"#/components/schemas/IpEntry"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ServerDetail":{"allOf":[{"$ref":"#/components/schemas/ServerSummary"},{"type":"object","properties":{"networking":{"type":"object","properties":{"primaryIp":{"type":"string","nullable":true,"example":"198.51.100.10"},"gateway":{"type":"string","nullable":true,"example":"198.51.100.1"},"additionalIps":{"type":"array","items":{"$ref":"#/components/schemas/IpEntry"}}}},"specs":{"type":"object","properties":{"vcpu":{"type":"integer"},"ramMb":{"type":"integer"},"ramGb":{"type":"integer"},"diskGb":{"type":"integer"},"bandwidthGb":{"type":"integer"},"os":{"type":"string"},"region":{"type":"string"}}}}}]},"Credentials":{"type":"object","properties":{"username":{"type":"string","example":"root"},"password":{"type":"string","example":"G7xK2mP9qR3s"},"ip":{"type":"string","example":"198.51.100.10","nullable":true},"sshCommand":{"type":"string","example":"ssh root@198.51.100.10","nullable":true}}},"ServerStats":{"type":"object","nullable":true,"properties":{"cpu":{"type":"number","example":12.4,"description":"CPU usage %"},"memoryUsed":{"type":"integer","example":1024,"description":"Used RAM in MB"},"memoryTotal":{"type":"integer","example":4096,"description":"Total RAM in MB"},"diskUsed":{"type":"integer","example":10,"description":"Used disk in GB"},"diskTotal":{"type":"integer","example":50,"description":"Total disk in GB"}}},"DeployServerRequest":{"type":"object","required":["label","productId","os"],"properties":{"label":{"type":"string","example":"prod-1","description":"Display name for the server"},"productId":{"type":"string","format":"uuid","description":"Plan ID from GET /products"},"region":{"type":"string","example":"OTWA IST","description":"Deployment region"},"os":{"type":"string","example":"ubuntu-2404","description":"OS template identifier"},"hostname":{"type":"string","example":"srv1.example.com","description":"Optional hostname (FQDN)"}}},"MessageResponse":{"type":"object","properties":{"message":{"type":"string"}}},"Addon":{"type":"object","properties":{"id":{"type":"string","example":"vpk7wjf5"},"name":{"type":"string","example":"8 Additional IPs"},"description":{"type":"string"},"type":{"type":"string","enum":["extra-ip","ip-class","backup"]},"price":{"type":"number","example":32},"proratedPrice":{"type":"number","example":15.47,"description":"Amount charged now based on days left in cycle"},"owned":{"type":"boolean","description":"true if the server already has an active add-on of the same type"}}},"AddonCatalog":{"type":"object","properties":{"addons":{"type":"array","items":{"$ref":"#/components/schemas/Addon"}},"daysRemaining":{"type":"integer","example":14},"billingCycleEnd":{"type":"string","format":"date-time","nullable":true}}},"PurchaseAddonRequest":{"type":"object","required":["addonId"],"properties":{"addonId":{"type":"string","example":"vpk7wjf5"}}},"PurchaseAddonResponse":{"type":"object","properties":{"addon":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"number"}}},"prorated":{"type":"number","example":15.47,"description":"Amount charged to wallet"},"daysRemaining":{"type":"integer","example":14},"newMonthlyPrice":{"type":"number","example":41.99,"description":"Server monthly price after this add-on is included"},"allocatedIpCount":{"type":"integer","example":8,"description":"Zero for backup add-ons"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"API key lacks required permission","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/account":{"get":{"operationId":"getAccount","summary":"Get account info","description":"Returns the authenticated account details including balance and tier.","tags":["Account"],"security":[{"bearerAuth":["account:read"]}],"responses":{"200":{"description":"Account details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/products":{"get":{"operationId":"listProducts","summary":"List available plans","description":"Returns all available server plans with pricing and specs. No authentication required.","tags":["Products"],"security":[],"responses":{"200":{"description":"List of plans","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}}}}}}},"/servers":{"get":{"operationId":"listServers","summary":"List servers","description":"Returns all servers in your account, each enriched with primary IP and all additional IPs.","tags":["Servers"],"security":[{"bearerAuth":["servers:read"]}],"responses":{"200":{"description":"List of servers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServerSummary"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"deployServer","summary":"Deploy server","description":"Provisions a new server. Deducts monthly cost from wallet balance. Server is ready in ~60 seconds.","tags":["Servers"],"security":[{"bearerAuth":["servers:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployServerRequest"}}}},"responses":{"201":{"description":"Server created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerSummary"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"description":"Insufficient wallet balance"}}}},"/servers/{id}":{"get":{"operationId":"getServer","summary":"Get server","description":"Returns full server details including structured networking and specs blocks.","tags":["Servers"],"security":[{"bearerAuth":["servers:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Server detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"terminateServer","summary":"Terminate server","description":"Permanently destroys the server, powers it off, and releases its IP. Irreversible.","tags":["Servers"],"security":[{"bearerAuth":["servers:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Termination queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/servers/{id}/credentials":{"get":{"operationId":"getServerCredentials","summary":"Get SSH credentials","description":"Returns the root username, password, primary IP, and a ready-to-use SSH command.","tags":["Servers"],"security":[{"bearerAuth":["servers:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Server credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credentials"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/servers/{id}/stats":{"get":{"operationId":"getServerStats","summary":"Live resource stats","description":"Returns real-time CPU, RAM, and disk usage. Only available when server status is running.","tags":["Servers"],"security":[{"bearerAuth":["servers:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Live stats or null if unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerStats"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/servers/{id}/label":{"patch":{"operationId":"renameServer","summary":"Rename server","description":"Updates the display label of a server.","tags":["Servers"],"security":[{"bearerAuth":["servers:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["label"],"properties":{"label":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerSummary"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/servers/{id}/addons":{"get":{"operationId":"listServerAddons","summary":"List available add-ons","description":"Returns every add-on offered by the server's plan, each annotated with the prorated price to charge now and whether an add-on of that type is already active on this server. Only one add-on per type (extra-ip, ip-class, backup) can be active at a time.","tags":["Servers"],"security":[{"bearerAuth":["servers:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Add-on catalog for the server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddonCatalog"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"purchaseServerAddon","summary":"Purchase add-on","description":"Attaches an add-on to an already-running server. Charges the prorated amount to your wallet immediately and bumps the server's monthly price so the full add-on cost is included in future renewals. For extra-ip and ip-class add-ons the new IPs are routed to the VM at the network layer — you must configure them inside the guest OS yourself. Fails with 400 if an add-on of the same type is already active or if wallet balance is insufficient.","tags":["Servers"],"security":[{"bearerAuth":["servers:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseAddonRequest"}}}},"responses":{"200":{"description":"Add-on attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseAddonResponse"}}}},"400":{"description":"Duplicate type, insufficient balance, or allocation failed (wallet refunded)"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/servers/{id}/power/{action}":{"post":{"operationId":"serverPowerAction","summary":"Power action","description":"Perform a power action on a server: start, stop, or reboot.","tags":["Servers"],"security":[{"bearerAuth":["servers:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["start","stop","reboot"]}}],"responses":{"200":{"description":"Action queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"tags":[{"name":"Account","description":"Account profile and balance"},{"name":"Products","description":"Available server plans and pricing"},{"name":"Servers","description":"Deploy, manage, and monitor cloud servers"}]}