Register your routes
Add the directory that contains your request handlers inboot():
src/Plugin.php
src/ directory is usually enough. Point it at a subdirectory, such as __DIR__ . '/RequestHandlers', if you want to limit the scan.
Anatomy of a handler
src/RequestHandlers/HelloRequestHandler.php
RequestHandlerInterface. The base class supplies the path prefix and the middleware stack; the #[Route] attribute supplies the rest of the path and the HTTP method.
Choose a base class
Prefixes and middleware are inherited, so
#[Route(path: '/settings/hello')] on an admin view handler becomes GET /admin/settings/hello.
Route attributes
Path syntax
Route parameters arrive as request attributes:
priority: Priority::HIGH when it would otherwise be shadowed by a more generic pattern.
Read the request
RequestBodyParserMiddleware decodes JSON and form bodies into a stdClass, so use property_exists() before reading optional fields.
Return a response
Shape your JSON with resources
Return aJsonSerializable resource rather than raw arrays, so your API matches the rest of Aikeedo:
src/Presentation/Resources/NoteResource.php
Presentation\Resources\ListResource wraps collections as {"object": "list", "data": [...]}, and CountResource wraps counts, which keeps your endpoints consistent with the core API.
Errors
Throw, and letExceptionMiddleware translate the exception into a response:
Custom middleware
Middleware is a plain PSR-15 class, so you can autowire dependencies into it:src/Middlewares/RequireFeatureMiddleware.php
#[Middleware(RequireFeatureMiddleware::class)] on the handler or on a base class of your own.
Group routes with your own base class
src/RequestHandlers/NotesApi.php
NotesApi are served under /api/notes, with the standard API middleware plus your feature check.