{
  "openapi": "3.1.0",
  "info": {"title":"HubNova Developer API","version":"2026-10-12","description":"Sandbox-first, scope-bound access to HubNova-owned functionality. This is not a general Discord proxy. Message publication requires a separate proposal, checksum and confirmation step."},
  "servers": [{"url":"https://hubnova.nl/v1"}],
  "components": {
    "securitySchemes": {"serviceKey":{"type":"http","scheme":"bearer","bearerFormat":"hn_test_..."}},
    "schemas": {
      "Problem": {"type":"object","required":["type","title","status","code"],"properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"requestId":{"type":"string"}}},
      "MessageDocument": {"type":"object","required":["surface","title","content","color"],"properties":{"surface":{"type":"string"},"locale":{"enum":["nl","en"]},"title":{"type":"string","maxLength":256},"content":{"type":"string","maxLength":4000},"color":{"type":"integer","minimum":0,"maximum":16777215},"footer":{"type":"string","maxLength":2048},"thumbnailUrl":{"type":["string","null"],"format":"uri"},"imageUrl":{"type":["string","null"],"format":"uri"}}}
    }
  },
  "security": [{"serviceKey":[]}],
  "paths": {
    "/meta": {"get":{"security":[],"summary":"Public API metadata","responses":{"200":{"description":"API metadata"}}}},
    "/servers": {"get":{"summary":"List authorised synthetic or installed servers","responses":{"200":{"description":"Server list"},"401":{"description":"Invalid key"},"403":{"description":"Missing servers:read scope"}}}},
    "/servers/{id}/capabilities": {"get":{"summary":"Describe effective capabilities without granting access","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Effective capabilities"},"404":{"description":"Unknown server"}}}},
    "/servers/{id}/messages": {"get":{"summary":"Read effective message documents","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Message catalog; requires messages:read"},"403":{"description":"Missing messages:read scope"}}}},
    "/servers/{id}/messages/preview": {"post":{"summary":"Validate and preview a message without changing state","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Validated preview; requires messages:preview"},"422":{"description":"Invalid message"}}}},
    "/servers/{id}/messages/proposals": {"post":{"summary":"Create an immutable publication proposal","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Proposal and checksum; requires messages:propose"}}}},
    "/servers/{id}/messages/proposals/{proposalId}/publish": {"post":{"summary":"Publish a proposal using its checksum and exact confirmation phrase","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"proposalId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Published revision; requires messages:publish"},"400":{"description":"Checksum or confirmation mismatch"}}}},
    "/publications": {"get":{"summary":"List authorised HubNova publications","responses":{"200":{"description":"Publication list"},"403":{"description":"Missing publications:read scope"}}}},
    "/events": {"get":{"summary":"List authorised HubNova events","responses":{"200":{"description":"Event list"},"403":{"description":"Missing events:read scope"}}}},
    "/roadmap": {"get":{"summary":"List authorised roadmap items","responses":{"200":{"description":"Roadmap list"},"403":{"description":"Missing roadmap:read scope"}}}},
    "/tickets": {"post":{"summary":"Create a bounded support ticket","responses":{"202":{"description":"Accepted"},"403":{"description":"Missing tickets:create scope"}}}}
  }
}
