Skip to content

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.

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 instance
const consoleInstance = betterConsole({
connectionTokenHash: process.env.BETTER_CONSOLE_TOKEN_HASH!,
sessions: { autoApprove: process.env.NODE_ENV === "development" },
});
// 2. Pass it to UseBetter Tenant
const tenant = betterTenant({
database: ...,
tenantResolver: ...,
console: consoleInstance, // <--- Registers tenant endpoints automatically
});

This automatically registers the tenant product with all its endpoints (/tenants, /tenants/:id, etc.).

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 ...
],
});
FieldTypeDescription
idstringShort identifier. Used in the route path (e.g., "tenant"/.well-known/better/tenant/*).
namestringDisplay name shown in the Console UI (e.g., "UseBetter Tenant").
endpointsConsoleProductEndpoint[]Array of endpoint definitions.
FieldTypeDefaultDescription
method"GET" | "POST" | "PATCH" | "DELETE"(required)HTTP method.
pathstring(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.
requiredPermissionConsolePermission"read"Minimum permission level required to access this endpoint.

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: "..." } };
}

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/tenants

All product endpoints require authentication — the router verifies the session token and checks permissions before calling your handler.

UseBetter Console registers these routes automatically. These routes are unauthenticated — they handle the session handshake and discovery before a session exists.

MethodPathDescription
GET/console/healthHealth check. Returns {"status":"ok"}.
GET/console/capabilitiesReturns registered products, auth methods, and permissions.
POST/console/session/initInitiates a session (auto-approve or magic link).
POST/console/session/verifyVerifies a magic link code. Only registered when adapter is configured.
GET/console/session/pollPolls magic link session status. Only registered when adapter is configured.
POST/console/session/claimClaims a verified magic link session. Only registered when adapter is configured.

All routes are prefixed with /.well-known/better/ by the Hono middleware.

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.