skills/a0-development/references/api-webui.md
/a0/helpers/api.py/a0/api/AGENTS.md/a0/helpers/ws.py/a0/webui/AGENTS.md/a0/webui/components/AGENTS.md, /a0/webui/js/AGENTS.md/a0/webui/js/extensions.jsHTTP API handlers derive from helpers.api.ApiHandler:
from flask import Request, Response
from helpers.api import ApiHandler
class MyEndpoint(ApiHandler):
@classmethod
def get_methods(cls) -> list[str]:
return ["POST"]
async def process(self, input: dict, request: Request) -> dict | Response:
return {"ok": True}
Defaults from ApiHandler:
| Method | Default |
|---|---|
requires_loopback() | False |
requires_api_key() | False |
requires_auth() | True |
get_methods() | ["POST"] |
requires_csrf() | requires_auth() |
Override these only when the endpoint contract requires it. Keep auth and CSRF protection intact for browser-facing state changes.
helpers.api.register_api_route(...) registers:
/api/<path:path>
Resolution:
api/<name>.py becomes /api/<name>.plugins/<plugin>/api/<handler>.py becomes /api/plugins/<plugin>/<handler>.Return a Flask Response for files, redirects, custom status codes, and plain text. Return a dictionary for JSON success payloads.
Direct files under api/*.py require matching api/*.py.dox.md.
WebSocket handlers live in api/ws_*.py or plugin API folders and derive from helpers.ws.WsHandler:
from helpers.ws import WsHandler
class MyHandler(WsHandler):
async def process(self, event: str, data: dict, sid: str) -> dict | None:
return {"ok": True}
WsHandler mirrors ApiHandler security flags: auth defaults to True, CSRF defaults to auth, API-key and loopback default to False. Handlers should validate event data before using it and avoid returning secrets or unfiltered exception details.
Follow the nearest WebUI DOX before changing frontend files:
webui/AGENTS.md for the shell, CSS, assets, vendor, and extension loader.webui/js/AGENTS.md for stores, modals, API helpers, and JS infrastructure.webui/components/AGENTS.md and child docs for Alpine components.Patterns:
template x-if guard before using $store.<name>.createStore from /js/AlpineStore.js.openModal(path) and closeModal() from /js/modals.js.config.* and modal-only state/actions to context.*.api/*.py modules.