Skip to content

defineApi

The defineApi function is the entry point for defining your API structure. It creates an ApiDefinition container that lets you chain route definitions together, building a fully-typed map of your API that can be shared with the client.

Conventionally, this is defined in a shared file (e.g. api.ts) that is imported by both your server entry point and your client configuration.

api.ts
import { defineApi } from "@toapi/server";
export const api = defineApi()
.route("/users", import("./routes/users"))
.route("/users/:id", import("./routes/user-detail"));
function defineApi(options?: {
cache?: Cache;
oas?: { title: string; version: string };
logger?: Logger;
}): ApiDefinition<{}>;

Returns an empty ApiDefinition instance.

Option Type Default Description
cache Cache new PubSub() The cache / pub-sub instance used for tag-based revalidation and optional server-side response caching. Defaults to an in-process PubSub, which distributes invalidations but stores nothing. Pass a reference cache from @toapi/cache to enable server-side caching, or a shared implementation such as RedisCache when running multiple server instances.
oas { title: string; version: string } undefined When set, an OpenAPI 3.1 document is generated from your routes and served at <basePath>/__tapi/openapi.json. See generateOpenAPISchema.
logger Logger console.error Logger used by the request handler to report errors thrown by route handlers and cache operations. When omitted, errors are logged via console.error.
interface Logger {
error?: (error: unknown) => void | Promise<void>;
}

Pass any object that implements this shape — for example a Pino or Winston instance, or a custom function that ships errors to your observability platform.

import { defineApi } from "@toapi/server";
export const api = defineApi({
logger: {
error: (error) => reportToSentry(error),
},
});

Registers a route at a specific path.

  • Parameters:
    • path: A string representing the URL path. It supports:
      • Static segments: /users
      • Dynamic parameters: /users/:id
      • Wildcards: /files/* or /files/*path
    • module: A route object, or a Promise that resolves to a module containing the route handlers (usually via import()). Deferring with import() keeps route implementations out of the bundle until first hit.
  • Returns: The same ApiDefinition instance, re-typed to include the added route in its type signature so calls can be chained.

Invalidates cached responses tagged with the given tags by calling cache.delete(tags). Use it to purge stale entries from outside a request handler (for example a background job).

await api.invalidate(["books", "book:42"]);

Matches the exact URL path.

.route("/health", import("./routes/health"))

Matches a segment of the path and passes it to the handler.

.route("/posts/:postId/comments/:commentId", import("./routes/comment"))

In the handler these are accessed via req.params().postId and req.params().commentId.

Matches everything remaining in the path.

// Matches /files/images/logo.png
.route("/files/*path", import("./routes/files"))

In the handler this is accessed via req.params().path (which would be "images/logo.png").

The primary purpose of defineApi is to build a TypeScript type representing your entire API surface. This type is inferred automatically as you chain .route() calls, and is consumed by createFetchClient as typeof api to produce the fully-typed client.