| name | mas-api-contract |
| description | Define backend API contract standards for FastAPI services. Use when adding or refactoring HTTP/WebSocket endpoints in app/api, designing request/response schemas in app/models/schema.py, standardizing status/error contracts, and maintaining backward compatibility for clients. |
MAS API Contract
Objective
Keep backend API interfaces stable, consistent, and easy to consume.
Global Constraints
Apply these constraints while using this skill.
- Make minimal necessary changes first; avoid broad refactors unless explicitly requested.
- Align with current code style and existing project conventions in the touched module.
- Avoid over-engineering, over-abstraction, and defensive programming that does not match existing code patterns.
- Study similar existing implementations deeply before coding and follow established local patterns.
Scope
Apply to:
- HTTP endpoints under
app/api/*.
- Request/response schema models in
app/models/schema.py.
- WebSocket message contracts used by backend services.
Current dev baseline:
- Keep FastAPI responses aligned with
OutBase-style envelopes used in app/models/schema.py.
- Keep WebSocket contracts aligned with current envelope conventions already used by
app/api/core.py and WS command routes.
Contract Principles
- Keep one clear contract per endpoint action.
- Keep request and response types explicit and version-safe.
- Keep error semantics predictable across endpoints.
- Keep compatibility-first behavior for public contract changes.
Endpoint Naming Rules
- Use resource-oriented prefixes:
/api/<resource>.
- Keep action suffixes explicit for non-CRUD operations (
/start, /stop, /reorder).
- Keep endpoint names concise and unambiguous.
- Avoid introducing equivalent endpoints with different verbs/paths.
- For
POST query-style endpoints such as combobox/list options, prefer one endpoint with an explicit request-body discriminator over splitting equivalent endpoints by implementation type.
- Do not create parallel paths like
/xxx-foo and /xxx-bar solely because the backend reads different config books; keep the path semantic stable and put the selected type in the body.
Request/Response Schema Rules
- Use
*In for request models.
- Use
*Out for response models.
- Use shared
OutBase for common response envelope fields when applicable.
- Bind endpoint
response_model explicitly.
- Do not return raw untyped dicts if a schema model exists.
- When a request needs to choose between known plan/script/config families, model that selector explicitly instead of encoding it in the URL path or handler name.
- Define or update request/response data models in
app/models/schema.py before wiring a new route.
- Create routes in the corresponding
app/api/ module and keep route handlers as thin transport adapters around schema models and backend calls.
Field Naming Rules
- Keep external API fields stable and consistent per established style.
- Reuse canonical shared semantic names via
mas-schema-naming.
- Avoid introducing synonym fields for the same semantic.
- Keep ID fields consistent by entity (
scriptId, queueId, userId, etc.).
Error Contract Rules
- Return deterministic error structure (
code, status, message) for handled failures.
- Convert domain exceptions at API boundary only.
- Keep human-readable message plus machine-usable code.
- Avoid leaking internal stack details in API response payloads.
Status Code And Result Semantics
- Use API-level success response only when operation contract succeeds.
- Keep business-level failure represented in standardized error response.
- Keep the same endpoint semantics across modules (scripts/queue/plan/emulator).
WebSocket Contract Rules
- Keep message envelope stable (
id, type, data).
- Keep signal/update/info/message type semantics explicit and documented.
- Keep WS command payload contract aligned with HTTP command equivalents when both exist.
- Keep heartbeat and close semantics centralized in core WS flow.
Compatibility And Evolution
- Prefer additive changes over breaking changes.
- Deprecate fields/endpoints with transition period.
- Keep backward read compatibility when renaming request fields.
- Document any breaking contract change before merge.
- For OpenAPI-exposed schema fields already consumed by generated frontend clients, avoid rewriting a stable flat
Literal[...] field into Union[...] plus shared type aliases unless you have verified that the generated TypeScript runtime exports remain unchanged.
- Treat documented local integration entrypoints as compatibility surfaces too; do not rename or repurpose stable paths such as the documented MCP SSE endpoint without an explicit migration plan.
- After backend API changes, regenerate frontend API clients from
http://127.0.0.1:36163/openapi.json with openapi --output ./src/api --client axios instead of hand-editing generated TypeScript.
- When testing new API calls from the frontend, remember that plain
yarn dev can use the remote dev backend; start the local backend first when verifying local API changes.
Layer Boundary Rules
api layer owns transport contract mapping only.
schema layer owns model definitions only.
core/task/services own business execution and integration logic.
- Apply
mas-module-boundary for placement and dependency checks.
API Review Checklist
- Endpoint path/action naming is clear and non-duplicative.
*In/*Out models are present and explicit.
response_model is declared.
- Error contract shape is consistent.
- Field names align with existing canonical semantics.
- WebSocket payload changes preserve envelope compatibility.
- Contract changes include compatibility notes.
POST endpoints do not multiply paths when a body selector would keep the contract simpler.
- Changes to documented localhost endpoints or startup assumptions were reviewed for user- and tool-facing compatibility, not just backend correctness.
- OpenAPI regeneration is handled as a separate generated-code step, and generated files are not manually edited.