Product Registration
UseBetter Console discovers what data to show by querying registered product endpoints. Products register themselves with the console instance, and the Console UI automatically discovers them via the /capabilities endpoint.
Registering UseBetter Tenant
Section titled “Registering UseBetter Tenant”If you are using @usebetterdev/tenant, it has built-in support for UseBetter Console. Simply pass your console instance to the betterTenant configuration:
import { betterConsole } from "@usebetterdev/console";import { betterTenant } from "@usebetterdev/tenant";
// 1. Create the console instanceconst consoleInstance = betterConsole({ connectionTokenHash: process.env.BETTER_CONSOLE_TOKEN_HASH!, sessions: { autoApprove: process.env.NODE_ENV === "development" },});
// 2. Pass it to UseBetter Tenantconst tenant = betterTenant({ database: ..., tenantResolver: ..., console: consoleInstance, // <--- Registers tenant endpoints automatically});This automatically registers the tenant product with all its endpoints (/tenants, /tenants/:id, etc.).
Registering custom products
Section titled “Registering custom products”For your own products or custom features, use registerProduct() on the console instance:
import { betterConsole } from "@usebetterdev/console";import type { ConsoleProduct } from "@usebetterdev/console";
const consoleInstance = betterConsole({ connectionTokenHash: process.env.BETTER_CONSOLE_TOKEN_HASH!, sessions: { autoApprove: process.env.NODE_ENV === "development" },});
consoleInstance.registerProduct({ id: "my-product", name: "My Custom Product", endpoints: [ { method: "GET", path: "/items", requiredPermission: "read", handler: async (request) => { // ... implementation ... return { status: 200, body: [] }; }, }, // ... more endpoints ... ],});ConsoleProduct interface
Section titled “ConsoleProduct interface”| Field | Type | Description |
|---|---|---|
id | string | Short identifier. Used in the route path (e.g., "tenant" → /.well-known/better/tenant/*). |
name | string | Display name shown in the Console UI (e.g., "UseBetter Tenant"). |
endpoints | ConsoleProductEndpoint[] | Array of endpoint definitions. |
ConsoleProductEndpoint interface
Section titled “ConsoleProductEndpoint interface”| Field | Type | Default | Description |
|---|---|---|---|
method | "GET" | "POST" | "PATCH" | "DELETE" | (required) | HTTP method. |
path | string | (required) | Path relative to the product mount. Supports :param segments (e.g., "/tenants/:id"). |
handler | (request: AuthenticatedConsoleRequest) => Promise<ConsoleResponse> | (required) | Request handler. Receives an authenticated request with session and params populated. |
requiredPermission | ConsolePermission | "read" | Minimum permission level required to access this endpoint. |
Handler request
Section titled “Handler request”Product endpoint handlers receive an AuthenticatedConsoleRequest — a ConsoleRequest with a guaranteed session field:
handler: async (request) => { // request.session is always defined (auth is handled by the router) const { email, permissions } = request.session;
// URL params from :param segments const tenantId = request.params.id;
// Query string parameters const limit = request.query.limit;
// Request body (parsed JSON) const body = request.body;
return { status: 200, body: { data: "..." } };}Route pattern
Section titled “Route pattern”Registered product endpoints are served under:
/.well-known/better/<productId>/<path>For example, a product with id: "tenant" and an endpoint with path: "/tenants" is accessible at:
GET /.well-known/better/tenant/tenantsAll product endpoints require authentication — the router verifies the session token and checks permissions before calling your handler.
Built-in routes
Section titled “Built-in routes”UseBetter Console registers these routes automatically. These routes are unauthenticated — they handle the session handshake and discovery before a session exists.
| Method | Path | Description |
|---|---|---|
GET | /console/health | Health check. Returns {"status":"ok"}. |
GET | /console/capabilities | Returns registered products, auth methods, and permissions. |
POST | /console/session/init | Initiates a session (auto-approve or magic link). |
POST | /console/session/verify | Verifies a magic link code. Only registered when adapter is configured. |
GET | /console/session/poll | Polls magic link session status. Only registered when adapter is configured. |
POST | /console/session/claim | Claims a verified magic link session. Only registered when adapter is configured. |
All routes are prefixed with /.well-known/better/ by the Hono middleware.
Capabilities endpoint
Section titled “Capabilities endpoint”The capabilities endpoint (GET /.well-known/better/console/capabilities) returns information about your Console setup:
{ "products": ["tenant"], "authMethods": ["magic_link"], "permissions": ["read", "write", "admin"]}The Console UI calls this endpoint to discover what products are available and which authentication method to use.
Next steps
Section titled “Next steps”- Configuration — full config reference, permissions, CORS
- Authentication — auth methods and session management
- Architecture — request flow and routing internals