Create backend endpoints by adding files to the api/ directory. Export named functions for each HTTP method.
// api/hello.ts export async function GET(req) { const name = req.query.name || 'World'; return { message: `Hello, ${name}!` }; } export async function POST(req) { const { text } = req.body; return { created: true, text }; }
This creates GET /api/hello and POST /api/hello.
| Property | Type | Description |
|---|---|---|
method | string | HTTP method (GET, POST, etc.) |
url | string | Request pathname |
query | object | Parsed query string parameters |
params | object | Dynamic route parameters |
body | any | Parsed JSON body (non-GET) |
files | array | Uploaded files (multipart) |
headers | object | Request headers |
// api/users/[id].ts export async function GET(req) { const userId = req.params.id; return { user: { id: userId, name: 'Alice' } }; } // GET /api/users/42 → { user: { id: "42", name: "Alice" } }
Throw an object with status and message to return an error response:
export async function GET(req) { const item = await db.find(req.params.id); if (!item) { throw { status: 404, message: 'Item not found' }; } return item; }
Multipart form data is parsed automatically. Files are available on req.files:
export async function POST(req) { for (const file of req.files) { console.log(file.fileName, file.size, file.contentType); // file.data is a Buffer } return { uploaded: req.files.length }; }