API Routes
Embedded Hono API endpoint reference.
Was this page helpful?
Hono is the canonical API router inside the TanStack Start application. The single
src/routes/api/$.ts adapter mounts src/api/app.ts; domain
handlers under src/api/routes/ call server-only services for business logic.
Normal endpoints validate JSON, route parameters, and consumed query values at
Hono before calling a service. Malformed JSON and invalid fields return 400:
{ "ok": false, "error": "invalid_request", "message": "Invalid request." }Use Zod schemas with validateJson, validateParam, or validateQuery from
@/api/validation. Read the inferred value with c.req.valid(...):
import { Hono } from "hono";
import { z } from "zod";
import { validateJson } from "@/api/validation";
import { processData } from "@/services/example/service";
const schema = z.object({ name: z.string().trim().min(1).max(80) });
export const exampleRoutes = new Hono().post(
"/",
validateJson(schema),
async (c) => {
const input = c.req.valid("json");
const result = await processData(input);
return c.json(result, 201);
},
);Keep authentication, authorization, and business behavior in the service. Add
the existing same-origin mutation guard for cookie-authenticated writes.
The private-file upload routes are the multipart exception: POST /api/files
and POST /api/files/avatar accept exactly one file field. Other JSON
mutation routes retain their JSON-only guards.
Auth email values are trimmed; passwords remain exactly as entered. Signup
password strength and credential acceptance remain Auth service/provider
responsibilities. No input validator runs ahead of Stripe webhook signature
verification: that endpoint reads the original raw body.
http://localhost:3000/apihttps://yourdomain.com/api/api/files uploads personal files, while /api/files/:fileKey reads or
removes them. /api/files/avatar uploads, replaces, reads, or removes the
authenticated user's picture. These routes use the caller's Supabase session
and return private, uncached reads. See Storage setup and endpoint reference
for methods, response statuses, multipart examples, and limits.
Auth actions and several customer-facing service failures return an ok flag
and a redirect path that carries the visible status or error:
{
"ok": false,
"redirectPath": "/path?error=message&error_description=details"
}Validation, search, webhook, and test-only routes keep their route-specific HTTP status and response body instead of being forced into this shape.
Add the endpoint to the Hono module that owns its domain. Keep business logic in a service and leave the TanStack Start catch-all unchanged.
Use the validated route example above as the starting
point. Define your input schema and implement processData in
src/services/example/service.ts; the service receives the validated input.
Mount a new domain module in src/api/app.ts with
apiApp.route('/example', exampleRoutes). Existing domains should add their
endpoint to the current route module instead.