Define an API action
Qino's API is an action tree. A branch names a path segment; a verb such as get or post describes what happens at that path. The first app already uses this pattern for GET /api/hello.
A public action
import { Access, App, sys } from "@qino/qino";
const app = new App();
app.apiTree = {
hello: {
get: {
description: "Say hello",
access: Access.PUBLIC,
execute: () => ({ message: "Hello from Qino" }),
},
},
};
await app.init();
sys.serve({ port: 8080 }, app.fetch);
The branch hello becomes part of the URL, get serves the HTTP method, and execute returns the response value. Access.PUBLIC makes the action callable without signing in.
Path parameters
A :name branch captures a path segment. A schema can validate and convert it before the action runs:
import { Access, App, s } from "@qino/qino";
const app = new App();
app.apiTree = {
items: {
":id": {
paramSchema: s.number(),
get: {
description: "Read an item",
access: Access.PUBLIC,
execute: ({ id }) => ({ id }),
},
},
},
};
This declares GET /api/items/:id. Qino converts id to a number before passing it to execute. Add a resolve function on the parameter branch when that value should become an application object, such as a database row.
Access and validation
An action may declare input, query and output schemas. Its access check decides who may use it; guard can also check the validated parameters for a particular call. An action without an explicit access rule is denied by default.
Keep access rules close to the action they protect. For login factors, sessions and step-up checks, read Authentication.
More than HTTP
The same action tree can be exposed as MCP tools. Read the MCP guide before enabling that interface for an application.
The action fields are defined in Qino's API types; the path and validation behavior is covered by runtime tests.