{"openapi":"3.1.0","info":{"title":"BaseKV Agent API","version":"1.0.0","description":"Machine-facing API for BaseKV workspace operations. All endpoints require bearer API tokens."},"servers":[{"url":"https://basekv.pages.dev"}],"tags":[{"name":"identity","description":"Token identity and account context"},{"name":"instances","description":"Database instance lifecycle operations"}],"components":{"securitySchemes":{"BearerApiToken":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"Service-account API token issued by BaseKV."}},"schemas":{"PlanLimits":{"type":"object","properties":{"maxDatabases":{"type":"integer","nullable":true},"maxStorageMb":{"type":"integer","nullable":true},"maxRequestsPerDay":{"type":"integer","nullable":true}}},"Usage":{"type":"object","properties":{"current_count":{"type":"integer"},"limit_count":{"type":"integer","nullable":true},"usage_date":{"type":"string","format":"date"}}},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}},"security":[{"BearerApiToken":[]}],"paths":{"/api/v1/whoami":{"get":{"operationId":"whoami","tags":["identity"],"summary":"Get token identity and quota context","description":"Validates bearer token and returns account/service-account identity with plan and daily usage.","responses":{"200":{"description":"Token is valid","content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string"},"service_account_id":{"type":"string"},"token_id":{"type":"string"},"token_prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"plan":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"limits":{"$ref":"#/components/schemas/PlanLimits"}}},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["account_id","service_account_id","token_id","token_prefix","scopes"]}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Daily quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/instances":{"get":{"operationId":"listInstances","tags":["instances"],"summary":"List account instances","description":"Returns all instances tied to subscriptions in the token account.","x-required-scopes":["db.instances.read"],"responses":{"200":{"description":"Instances returned","content":{"application/json":{"schema":{"type":"object","properties":{"instances":{"type":"array","items":{"type":"object"}},"plan":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"limits":{"$ref":"#/components/schemas/PlanLimits"}}},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["instances"]}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Daily quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createInstance","tags":["instances"],"summary":"Create instance","description":"Creates an instance on the least-loaded online node in the selected region.","x-required-scopes":["db.instances.write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2},"region":{"type":"string"},"protocol":{"type":"string","enum":["redis","memcached","both"]},"log_level":{"type":"string"}},"required":["name"]}}}},"responses":{"201":{"description":"Instance request accepted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"node_id":{"type":"string"},"region":{"type":"string"},"protocol":{"type":"string"},"auth_required":{"type":"boolean"},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["id","name","status","node_id","protocol"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"No available nodes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/instances/{id}":{"delete":{"operationId":"deleteInstance","tags":["instances"],"summary":"Delete instance","description":"Deletes an instance. Uses async deprovisioning by default, and may immediately remove control-plane state when node health is stale/offline or force=true.","x-required-scopes":["db.instances.write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean"},"description":"Force immediate control-plane deletion (skips asynchronous node deprovisioning)."}],"responses":{"200":{"description":"Instance removed from control plane immediately","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["deleted"]},"usage":{"$ref":"#/components/schemas/Usage"},"mode":{"type":"string","enum":["immediate","fallback"]},"reason":{"type":"string"}},"required":["id","status"]}}}},"202":{"description":"Delete request accepted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["deleting"]},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["id","status"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/instances/{id}/credentials":{"get":{"operationId":"getInstanceCredentialsMetadata","tags":["instances"],"summary":"Get credential metadata","description":"Returns endpoint and masked password state for an instance. Does not return the plaintext password.","x-required-scopes":["db.instances.read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Credential metadata returned","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"protocol":{"type":"string"},"node_id":{"type":"string"},"host":{"type":"string"},"ports":{"type":"object","properties":{"redis":{"type":"integer","nullable":true},"memcached":{"type":"integer","nullable":true},"http":{"type":"integer","nullable":true}}},"password_set":{"type":"boolean"},"password_masked":{"type":"string","nullable":true}},"required":["id","name","protocol","node_id","host","ports","password_set"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/instances/{id}/credentials/reveal":{"post":{"operationId":"revealInstancePassword","tags":["instances"],"summary":"Reveal instance password","description":"Returns the plaintext password for a single owned instance.","x-required-scopes":["db.instances.write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Password returned","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"protocol":{"type":"string"},"host":{"type":"string"},"redis_port":{"type":"integer","nullable":true},"password":{"type":"string"}},"required":["id","name","protocol","host","password"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"No password configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/instances/{id}/credentials/rotate":{"post":{"operationId":"rotateInstancePassword","tags":["instances"],"summary":"Rotate instance password","description":"Generates a new instance password and requests a restart to apply it.","x-required-scopes":["db.instances.write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Rotation requested","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["restarting"]},"protocol":{"type":"string"},"host":{"type":"string"},"redis_port":{"type":"integer","nullable":true},"password":{"type":"string"},"message":{"type":"string"}},"required":["id","name","status","protocol","host","password"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Invalid state transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/instances/{id}/restart":{"post":{"operationId":"restartInstance","tags":["instances"],"summary":"Restart instance","description":"Marks an instance for restart. The agent performs stop/start and updates status.","x-required-scopes":["db.instances.write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Restart request accepted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["restarting"]},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["id","status"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or no active subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Invalid state transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}