Skip to main content

API Routes

Files named route.ts under the pastoria/ directory become server-side Express API handlers, mounted at the corresponding URL path.

Basic example

pastoria/api/greet/[name]/route.ts  →  Express route /api/greet/:name

A route.ts file default-exports an Express router:

import express from 'express';

const router = express.Router({mergeParams: true});

router.get<'/', {name: string}>('/', (req, res) => {
res.json({greeting: `Hello ${req.params.name}`});
});

export default router;

Key points

  • Use express.Router({mergeParams: true}) to access path params from the parent URL.
  • Dynamic segments in directory names (e.g. [name]) become Express path params (:name).
  • Route handlers are mounted at their directory path, so define handlers relative to /.
  • API routes support all Express methods (get, post, put, delete, etc.).

Catch-all routes

Use router.all() with a splat pattern to forward all requests to middleware or external handlers:

import express from 'express';
import {toNodeHandler} from 'better-auth/node';
import {auth} from '#src/lib/server/auth.js';

const router = express.Router();

router.all('/*splat', (req, res, next) => {
toNodeHandler(auth)(req, res).catch(next);
});

export default router;

This is useful for authentication endpoints, proxying, or any route that needs to handle multiple HTTP methods and sub-paths.

Code generation

When you add or remove a route.ts file, run code generation so the server entry picks it up:

pnpm generate

Note that route.ts changes are not auto-detected by the dev server's file watcher (which only watches .tsx files). You must run pnpm generate manually after adding or modifying API routes.