Skip to content

Express Endpoints quickstart

Create and call an Astro API route with Express-style request and response helpers.

View Markdown

Use Express-style routing and middleware in an Astro API endpoint. This example accepts JSON and returns a greeting.

npm install @astro-utils/express-endpoints @astrojs/node
astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' })
});
src/pages/api/hello.ts
import { ExpressRoute } from '@astro-utils/express-endpoints';
const router = new ExpressRoute();
router.body('json');
export const POST = router.route((req, res) => {
const name = typeof req.body?.name === 'string' ? req.body.name.trim() : '';
if (!name) {
res.status(400).json({ error: 'Name is required.' });
return;
}
res.json({ message: `Hello, ${name}!` });
});

Start your project with its dev script. Use the port printed by Astro in this request:

Terminal
curl -X POST http://localhost:4321/api/hello \
-H 'Content-Type: application/json' \
-d '{"name":"Alex"}'

The response is {"message":"Hello, Alex!"}. Sending {} returns status 400 and {"error":"Name is required."}. The example has no artificial delay or external service dependency.

router.body('multipart') makes uploaded files available on req.filesOne and req.filesMany. Use urlencoded for an ordinary HTML form or text for a text body. The default auto mode selects the parser from Content-Type.

See request examples and response examples.

For schema-based validation, install the Zod major version supported by the package’s express-zod-safe integration:

npm install zod@^4
src/pages/api/validated-hello.ts
import { ExpressRoute } from '@astro-utils/express-endpoints';
import { z } from 'zod';
const router = new ExpressRoute();
router.validate({
body: z.object({
name: z.string().trim().min(1)
})
});
export const POST = router.route((req, res) => {
res.json({ message: `Hello, ${req.body.name}!` });
});

By default, it’s relax validation that ignore extra properties, defaults to:

  • defaultSchemaObject: lax
  • missingSchemaBehavior: any

Validation applies to the next route created by this router. Review middleware and error handling before composing several handlers.