Skip to main content
Mastra 1.0 is available 🎉 Read announcement

registerApiRoute()

The registerApiRoute() function creates custom HTTP routes that integrate with the Mastra server. Routes can include OpenAPI metadata to appear in the Swagger UI documentation.

Import
Direct link to Import

import { registerApiRoute } from "@mastra/core/server";

Parameters
Direct link to Parameters

path
Direct link to path

The URL path for the route. Supports path parameters using :param syntax.

registerApiRoute("/items/:itemId", { ... })

Note: Paths cannot start with /api/ as this prefix is reserved for Mastra server routes.

options
Direct link to options

method:

'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'ALL'
HTTP method for the route

handler?:

Handler
Route handler function receiving Hono Context. Use either `handler` or `createHandler`, not both.

createHandler?:

(c: Context) => Promise<Handler>
Async factory function to create the handler. Use either `handler` or `createHandler`, not both.

middleware?:

MiddlewareHandler | MiddlewareHandler[]
Route-specific middleware functions

openapi?:

DescribeRouteOptions
OpenAPI metadata for Swagger UI documentation

OpenAPI Options
Direct link to OpenAPI Options

The openapi property accepts standard OpenAPI 3.1 operation fields from hono-openapi. Routes without an openapi property are not included in Swagger UI.

summary?:

string
Short summary of the operation

description?:

string
Detailed description of the operation

tags?:

string[]
Tags for grouping in Swagger UI. Defaults to ['custom'] if not specified.

deprecated?:

boolean
Mark the operation as deprecated

parameters?:

ParameterObject[]
Path, query, and header parameters

requestBody?:

RequestBodyObject
Request body specification

responses?:

ResponsesObject
Response specifications by status code

security?:

SecurityRequirementObject[]
Security requirements for the operation

Return Value
Direct link to Return Value

Returns an ApiRoute object to be passed to server.apiRoutes in the Mastra configuration.

Handler Context
Direct link to Handler Context

The handler receives a Hono Context object with access to:

handler: async (c) => {
// Get the Mastra instance
const mastra = c.get("mastra");

// Get request context
const requestContext = c.get("requestContext");

// Access path parameters
const itemId = c.req.param("itemId");

// Access query parameters
const filter = c.req.query("filter");

// Access request body
const body = await c.req.json();

// Return JSON response
return c.json({ data: "value" });
}

Examples
Direct link to Examples

Basic GET Route
Direct link to Basic GET Route

import { Mastra } from "@mastra/core";
import { registerApiRoute } from "@mastra/core/server";

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute("/health-check", {
method: "GET",
handler: async (c) => {
return c.json({ status: "ok" });
},
}),
],
},
});

Route with Path Parameters
Direct link to Route with Path Parameters

registerApiRoute("/users/:userId/posts/:postId", {
method: "GET",
handler: async (c) => {
const userId = c.req.param("userId");
const postId = c.req.param("postId");

return c.json({ userId, postId });
},
});

POST Route with Body
Direct link to POST Route with Body

registerApiRoute("/items", {
method: "POST",
handler: async (c) => {
const body = await c.req.json();
const mastra = c.get("mastra");

// Process the request...

return c.json({ id: "new-id", ...body }, 201);
},
});

Route with Middleware
Direct link to Route with Middleware

registerApiRoute("/protected", {
method: "GET",
middleware: [
async (c, next) => {
const token = c.req.header("Authorization");
if (!token) {
return c.json({ error: "Unauthorized" }, 401);
}
await next();
},
],
handler: async (c) => {
return c.json({ data: "protected content" });
},
});

Route with OpenAPI Documentation
Direct link to Route with OpenAPI Documentation

import { z } from "zod";

const ItemSchema = z.object({
id: z.string(),
name: z.string(),
price: z.number(),
});

registerApiRoute("/items/:itemId", {
method: "GET",
openapi: {
summary: "Get item by ID",
description: "Retrieves a single item by its unique identifier",
tags: ["Items"],
parameters: [
{
name: "itemId",
in: "path",
required: true,
description: "The item ID",
schema: { type: "string" },
},
],
responses: {
200: {
description: "Item found",
content: {
"application/json": {
schema: ItemSchema, // Zod schemas are converted to JSON Schema during OpenAPI generation
},
},
},
404: {
description: "Item not found",
},
},
},
handler: async (c) => {
const itemId = c.req.param("itemId");
return c.json({ id: itemId, name: "Example", price: 9.99 });
},
});

Using createHandler
Direct link to Using createHandler

For routes that need async initialization:

registerApiRoute("/dynamic", {
method: "GET",
createHandler: async (c) => {
// Perform async setup
const config = await loadConfig();

return async (c) => {
return c.json({ config });
};
},
});

Error Handling
Direct link to Error Handling

Throw errors with status codes using Hono's HTTPException:

import { HTTPException } from "hono/http-exception";

registerApiRoute("/items/:itemId", {
method: "GET",
handler: async (c) => {
const itemId = c.req.param("itemId");
const item = await findItem(itemId);

if (!item) {
throw new HTTPException(404, { message: "Item not found" });
}

return c.json(item);
},
});