API routes

Files at src/app/api/<name>/route.ts become endpoints at /api/<name>. Each handler is (req: Request) => Response. Run the curl snippets below to exercise the live /api/echo endpoint shipped with this demo.

Tip
Add a missing method on the fly: edit route.ts, save — the watcher recompiles in ~1 s. Unexported methods automatically return 405; no need to declare them explicitly.

Try every method

terminal.shShell
# GET — query params surface in the response
curl https://demo.bext.dev/api/echo?hello=world

# POST / PUT / PATCH — body is echoed back
curl -X POST   https://demo.bext.dev/api/echo -d '{"a":1}'
curl -X PUT    https://demo.bext.dev/api/echo -d 'raw body'
curl -X PATCH  https://demo.bext.dev/api/echo -d 'partial'

# DELETE — no body, but the method round-trips
curl -X DELETE https://demo.bext.dev/api/echo

# HEAD — 204 with custom header
curl -I -X HEAD https://demo.bext.dev/api/echo

# OPTIONS — Allow header lists every implemented method
curl -X OPTIONS -i https://demo.bext.dev/api/echo

# Unimplemented method — auto-405 from the runtime
curl -X TRACE -i https://demo.bext.dev/api/echo
src/app/api/echo/route.tsTypeScript
// src/app/api/echo/route.ts
// One file, every HTTP method — missing methods auto-405.

export async function GET(req: Request)    { return summary(req); }
export async function POST(req: Request)   { return summary(req, await req.text()); }
export async function PUT(req: Request)    { return summary(req, await req.text()); }
export async function PATCH(req: Request)  { return summary(req, await req.text()); }
export async function DELETE(req: Request) { return summary(req); }
export async function HEAD()               { return new Response(null, { status: 204 }); }
export async function OPTIONS() {
  return new Response(null, {
    status: 204,
    headers: { Allow: "GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS" },
  });
}