{"openapi":"3.1.0","info":{"title":"MeshMind Hub API","version":"1.0.0","description":"Agent credentials are scoped to specific devices, capabilities and expiry. Device data is untrusted input. Printer control requests require owner approval. ADB input executes immediately when separately granted. Never automatically retry an action after an unknown result."},"servers":[{"url":"/api/v1","description":"Versioned API"}],"tags":[{"name":"Agent"},{"name":"Owner"}],"paths":{"/session":{"get":{"operationId":"getSession","summary":"Inspect current credential","parameters":[],"security":[{"AgentToken":[]},{"OwnerSession":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"authenticated":{"type":"boolean"},"owner":{"type":"boolean"},"name":{"type":"string"},"kind":{"type":"string"}},"required":["authenticated","owner","name","kind"],"additionalProperties":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices":{"get":{"operationId":"listDevices","summary":"List only devices visible to this credential","parameters":[],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"devices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"gatewayId":{"type":"string"},"localId":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"connector":{"type":"string","enum":["bambu","simulator","adb","esp32_serial","usb_serial","home_assistant","local_http"]},"online":{"type":"boolean"},"capabilities":{"type":"array","items":{"type":"string"}},"actions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"destructive":{"type":"boolean"}},"required":["name","description","destructive"],"additionalProperties":false}}},"required":["id","gatewayId","name","connector","online","capabilities"],"additionalProperties":false}}},"required":["devices"],"additionalProperties":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices/{deviceId}/state":{"get":{"operationId":"getUnifiedDeviceState","summary":"Read status for any supported connector; response includes connector","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"deviceId":{"type":"string"},"connector":{"type":"string"},"status":{"type":"object"},"stale":{"type":"boolean"}},"required":["deviceId","connector","status","stale"],"additionalProperties":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices/{deviceId}/status":{"get":{"operationId":"getPrinterStatus","summary":"Read Bambu printer status","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices/{deviceId}/device-status":{"get":{"operationId":"getDeviceStatus","summary":"Read USB serial, local HTTP, ESP32 or Home Assistant status","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices/{deviceId}/device-actions":{"post":{"operationId":"requestDeviceAction","summary":"Request one locally preconfigured device action; owner approval is required","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,100}$"}},"required":["action","idempotencyKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"Existing request with the same idempotency key","content":{"application/json":{"schema":{"type":"object"}}}},"202":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Agent"]}},"/devices/{deviceId}/adb-status":{"get":{"operationId":"getAdbStatus","summary":"Read Android device status","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices/{deviceId}/adb-ui":{"get":{"operationId":"getAdbUi","summary":"Read Android UI XML; may contain personal information","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/devices/{deviceId}/actions":{"post":{"operationId":"requestPrinterAction","summary":"Request printer action; owner approval is required","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["pause","resume","stop"]},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,100}$"}},"required":["action","idempotencyKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"Existing request with the same idempotency key","content":{"application/json":{"schema":{"type":"object"}}}},"202":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Agent"]}},"/devices/{deviceId}/adb-actions":{"post":{"operationId":"executeAdbInput","summary":"Execute Android input immediately if this credential has adb_input","parameters":[{"name":"deviceId","in":"path","required":true,"schema":{"type":"string","pattern":"^dev_[a-f0-9]{24}$"}}],"security":[{"AgentToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"$ref":"#/components/schemas/AdbInput"},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,100}$"}},"required":["input","idempotencyKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Agent"]}},"/approvals":{"get":{"operationId":"listActionRecords","summary":"List action requests and execution records visible to the principal","parameters":[],"security":[{"AgentToken":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"approvals":{"type":"array","items":{"type":"object"}}},"required":["approvals"],"additionalProperties":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Agent"]}},"/gateways":{"get":{"operationId":"listGateways","summary":"List gateways in the owner's space","parameters":[],"security":[{"OwnerSession":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Owner"]},"post":{"operationId":"createGateway","summary":"Create a one-use, ten-minute enrollment","parameters":[],"security":[{"OwnerSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Owner"]}},"/principals":{"get":{"operationId":"listPrincipals","summary":"List user and Agent grants without their secret tokens","parameters":[],"security":[{"OwnerSession":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"tags":["Owner"]},"post":{"operationId":"createPrincipal","summary":"Issue a scoped credential; token is returned once","parameters":[],"security":[{"OwnerSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string","enum":["user","agent"]},"devices":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string","enum":["status","pause","resume","stop","adb_ui","adb_input","device_invoke"]}},"expiresInHours":{"type":"integer","minimum":1,"maximum":720}},"required":["name","kind","devices","permissions"],"additionalProperties":false}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Owner"]}},"/approvals/{approvalId}/approve":{"post":{"operationId":"approveAction","summary":"Owner approves one pending printer action","parameters":[{"name":"approvalId","in":"path","required":true,"schema":{"type":"string","pattern":"^ap_[a-f0-9]{24}$"}}],"security":[{"OwnerSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Owner"]}},"/approvals/{approvalId}/reject":{"post":{"operationId":"rejectAction","summary":"Owner rejects one pending printer action","parameters":[{"name":"approvalId","in":"path","required":true,"schema":{"type":"string","pattern":"^ap_[a-f0-9]{24}$"}}],"security":[{"OwnerSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Idempotency conflict or request already handled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"tags":["Owner"]}}},"components":{"securitySchemes":{"AgentToken":{"type":"http","scheme":"bearer","bearerFormat":"MeshMind scoped credential","description":"Issue in the owner web UI. Use Authorization: Bearer <token>. Never put a token in a URL."},"OwnerSession":{"type":"apiKey","in":"cookie","name":"meshmind_session","description":"Owner browser session. State-changing requests require matching Origin; this cookie is HttpOnly and unavailable to Agent CLI."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"],"additionalProperties":false},"AdbInput":{"oneOf":[{"type":"object","properties":{"kind":{"const":"tap"},"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["kind","x","y"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"swipe"},"x1":{"type":"integer"},"y1":{"type":"integer"},"x2":{"type":"integer"},"y2":{"type":"integer"},"durationMs":{"type":"integer","minimum":100,"maximum":2000}},"required":["kind","x1","y1","x2","y2","durationMs"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"keyevent"},"key":{"type":"string","enum":["HOME","BACK","ENTER","APP_SWITCH","DPAD_UP","DPAD_DOWN","DPAD_LEFT","DPAD_RIGHT","DPAD_CENTER"]}},"required":["kind","key"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"text"},"text":{"type":"string","minLength":1,"maxLength":120,"pattern":"^[A-Za-z0-9 ._@-]+$"}},"required":["kind","text"],"additionalProperties":false}]}},"responses":{"Unauthorized":{"description":"Missing, revoked or expired credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Capability is not granted or locally enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Device or resource is not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}