{"openapi":"3.1.0","info":{"title":"aidev Cloud API","version":"v1","description":"Your own aidev Cloud machines and SSH keys, with a personal access token (aidev_pat_…). The same operations as the MCP tools of the cloud:self and cloud:self:spend scopes."},"security":[{"bearer":[]}],"paths":{"/capi/v1/cloud/plans":{"get":{"operationId":"cloud_plans_list","summary":"List cloud plans","description":"The cloud plans on sale: hardware, pricePerHour (VND, what a new machine is billed at), slotState (whether one can be rented now) and the images. Read cloud_plan_get for the image ids and the price with a public IP before creating a machine.","parameters":[{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/plans/{ids}":{"get":{"operationId":"cloud_plan_get","summary":"Read one cloud plan","description":"One plan: hardware, slotState, images (ids, name, osFamily, isDefault), publicIpAvailable, pricePerHour and pricePerHourWithPublicIp (VND per hour, strings). Pass the price you will create at as expectedPricePerHour to cloud_my_instance_create.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the plan's 8-char ids"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/instances":{"get":{"operationId":"cloud_my_instances","summary":"List my cloud machines","description":"The owner's machines (status active by default; 'all' or one status), newest first, each with its SSH keys (fingerprints), connections, allowedActions and revision. Never a password.","parameters":[{"name":"status","in":"query","required":false,"schema":{"default":"active","type":"string","enum":["all","provisioning","active","error","terminated","completed"]}},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"cloud_my_instance_create","summary":"Rent a cloud machine","description":"Call only after the owner approved this exact text/decision in the conversation. Spends the owner's wallet: state the plan, image, hourly price and every SSH key fingerprint, and wait for the owner to agree. Prefer a one-off key generated for this session (sshPublicKeys) over saving it. At least one key, at most 5 (saved and one-off together); no password is ever given. Works for Ubuntu and Windows images; on Windows the SSH shell is PowerShell. expectedPricePerHour is the price read from cloud_plan_get: CLOUD_PRICE_CHANGED means it moved and nothing was created or charged. CLOUD_LOW_RUNWAY: with this machine the wallet plus Cloud credit keeps every running machine going for under 3 hours (details.runwayMinutes); nothing was created — tell the owner, and retry with acknowledgeLowRunway true only on their agreement. INSUFFICIENT_FUNDS: the wallet plus Cloud credit cannot pay the first hour. requestId is required: a fresh one per decision, the SAME one after a timeout; AGENT_REQUEST_FAILED on a resend means the first attempt may have run — read the row again before retrying with a NEW requestId.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"planIds":{"type":"string","minLength":8,"maxLength":8,"description":"the plan's ids (cloud_plans_list)"},"imageIds":{"type":"string","minLength":8,"maxLength":8,"description":"one of the plan's images (cloud_plan_get)"},"sshKeyIds":{"description":"saved keys (cloud_ssh_keys_list)","maxItems":5,"type":"array","items":{"type":"string","minLength":8,"maxLength":8}},"sshPublicKeys":{"description":"one-off PUBLIC keys, not saved to the account","maxItems":5,"type":"array","items":{"type":"string","maxLength":16384}},"usePublicIp":{"type":"boolean"},"label":{"type":"string","maxLength":100},"expectedPricePerHour":{"type":"string","pattern":"^\\d{1,12}$","description":"pricePerHour (or pricePerHourWithPublicIp) from cloud_plan_get, as read"},"acknowledgeLowRunway":{"description":"true only after the owner agreed to create despite CLOUD_LOW_RUNWAY (balance for under 3 hours)","type":"boolean"}},"required":["planIds","imageIds","expectedPricePerHour"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/instances/{ids}":{"get":{"operationId":"cloud_my_instance_get","summary":"Read one of my cloud machines","description":"One of the owner's machines: status, vmStatus, plan, image, pricePerHour, sshUser, sshKeys (fingerprint, algorithm, comment — every key on the machine; tell the owner about one they do not recognise), connections (protocol, host, port; empty until active), allowedActions and the revision the power and terminate tools need. Connect with ssh -i <private key> -p <port> <sshUser>@<host>; on Windows the SSH shell is PowerShell. Never returns a password. Every call is audited.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the machine's 8-char ids"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"cloud_my_instance_terminate","summary":"Terminate my cloud machine","description":"Call only after the owner approved this exact text/decision in the conversation. Deletes the machine and its disk for good; billing stops. Ask the owner to confirm the machine ids first. Only an active machine; send the revision from cloud_my_instance_get (AGENT_STALE: read it again). Never limited by the daily write quota. requestId is required: a fresh one per decision, the SAME one after a timeout; AGENT_REQUEST_FAILED on a resend means the first attempt may have run — read the row again before retrying with a NEW requestId.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the machine's 8-char ids"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}},{"name":"revision","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"the revision from cloud_my_instance_get"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/instances/{ids}/start":{"post":{"operationId":"cloud_my_instance_start","summary":"Start my stopped cloud machine","description":"Call only after the owner approved this exact text/decision in the conversation. Starts a stopped machine (vmStatus stopped → starting). Before calling, read the machine with cloud_my_instance_get and state the machine ids and the action, then wait for the owner to agree. A stopped machine keeps billing hourly: only cloud_my_instance_terminate stops the charge. The host confirms asynchronously; while the machine shows starting, stopping or restarting, do not send the command again. Send the revision: AGENT_STALE means the machine changed — read it again. AGENT_CLOUD_VM_STATE means the action is not in allowedActions now. One start, stop or restart a minute per machine. requestId is required: a fresh one per decision, the SAME one after a timeout; AGENT_REQUEST_FAILED on a resend means the first attempt may have run — read the row again before retrying with a NEW requestId.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the machine's 8-char ids"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"revision":{"type":"string","minLength":1,"description":"the revision from cloud_my_instance_get"}},"required":["revision"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/instances/{ids}/stop":{"post":{"operationId":"cloud_my_instance_stop","summary":"Stop my running cloud machine","description":"Call only after the owner approved this exact text/decision in the conversation. Stops a running machine (vmStatus running → stopping); it keeps billing while stopped. Before calling, read the machine with cloud_my_instance_get and state the machine ids and the action, then wait for the owner to agree. A stopped machine keeps billing hourly: only cloud_my_instance_terminate stops the charge. The host confirms asynchronously; while the machine shows starting, stopping or restarting, do not send the command again. Send the revision: AGENT_STALE means the machine changed — read it again. AGENT_CLOUD_VM_STATE means the action is not in allowedActions now. One start, stop or restart a minute per machine. requestId is required: a fresh one per decision, the SAME one after a timeout; AGENT_REQUEST_FAILED on a resend means the first attempt may have run — read the row again before retrying with a NEW requestId.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the machine's 8-char ids"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"revision":{"type":"string","minLength":1,"description":"the revision from cloud_my_instance_get"}},"required":["revision"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/instances/{ids}/restart":{"post":{"operationId":"cloud_my_instance_restart","summary":"Restart my running cloud machine","description":"Call only after the owner approved this exact text/decision in the conversation. Restarts a running machine (vmStatus running → restarting). Before calling, read the machine with cloud_my_instance_get and state the machine ids and the action, then wait for the owner to agree. A stopped machine keeps billing hourly: only cloud_my_instance_terminate stops the charge. The host confirms asynchronously; while the machine shows starting, stopping or restarting, do not send the command again. Send the revision: AGENT_STALE means the machine changed — read it again. AGENT_CLOUD_VM_STATE means the action is not in allowedActions now. One start, stop or restart a minute per machine. requestId is required: a fresh one per decision, the SAME one after a timeout; AGENT_REQUEST_FAILED on a resend means the first attempt may have run — read the row again before retrying with a NEW requestId.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the machine's 8-char ids"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"revision":{"type":"string","minLength":1,"description":"the revision from cloud_my_instance_get"}},"required":["revision"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/ssh-keys":{"get":{"operationId":"cloud_ssh_keys_list","summary":"List my saved SSH keys","description":"The SSH public keys saved in the owner's account (ids, name, fingerprint, algorithm, comment), most recently used first. Pass their ids as sshKeyIds to cloud_my_instance_create.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"cloud_ssh_key_add","summary":"Save an SSH public key","description":"Saves an SSH public key to the account. PUBLIC key only (the .pub file). Never send a private key. Saving is optional: cloud_my_instance_create also takes one-off keys. A key already saved is answered with the saved one (existing: true). At most 20 keys per account (CLOUD_SSH_KEY_LIMIT).","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[^\\p{Cc}\\p{Cs}\\p{Cf}\\u2028\\u2029\\uFDD0-\\uFDEF\\uFFFE\\uFFFF]*$"},"publicKey":{"type":"string","maxLength":16384,"description":"one OpenSSH public key line (the .pub file)"}},"required":["name","publicKey"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/capi/v1/cloud/ssh-keys/{ids}":{"delete":{"operationId":"cloud_ssh_key_remove","summary":"Delete a saved SSH key","description":"Call only after the owner approved this exact text/decision in the conversation. Deletes a saved key from the account for good. Machines already created with it keep it: the key list is written only when a machine is created. requestId is required: a fresh one per decision, the SAME one after a timeout; AGENT_REQUEST_FAILED on a resend means the first attempt may have run — read the row again before retrying with a NEW requestId.","parameters":[{"name":"ids","in":"path","required":true,"schema":{"type":"string","minLength":8,"maxLength":8,"description":"the saved key's 8-char ids"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A fresh uuid per decision; the SAME one when retrying after a timeout.","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Done"},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object"},"requestId":{"type":"string"}},"required":["code","message"]}}}}