patternjavascriptastroModerate
Astro server endpoints for API routes
Viewed 0 times
Astro 1.0+ (endpoints stable)
astro endpointsapi routesAPIRouteserver endpointsREST APIResponse
Error Messages
Problem
Astro is used for static content but needs API endpoints for form submissions, data fetching, or webhooks. Without endpoints, developers add a separate API server.
Solution
Create .ts files in src/pages/api/ that export HTTP method handlers:
// src/pages/api/users/[id].ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params, request, locals }) => {
const { id } = params;
const user = await db.user.findUnique({ where: { id } });
if (!user) {
return new Response(JSON.stringify({ error: 'Not found' }), {
status: 404,
headers: { 'Content-Type': 'application/json' }
});
}
return new Response(JSON.stringify(user), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
};
export const PUT: APIRoute = async ({ request, params }) => {
const body = await request.json();
const updated = await db.user.update({ where: { id: params.id }, data: body });
return Response.json(updated); // shorthand in newer Astro
};
export const DELETE: APIRoute = async ({ params }) => {
await db.user.delete({ where: { id: params.id } });
return new Response(null, { status: 204 });
};
// Prerender: false means this endpoint is always server-rendered
export const prerender = false;
// src/pages/api/users/[id].ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params, request, locals }) => {
const { id } = params;
const user = await db.user.findUnique({ where: { id } });
if (!user) {
return new Response(JSON.stringify({ error: 'Not found' }), {
status: 404,
headers: { 'Content-Type': 'application/json' }
});
}
return new Response(JSON.stringify(user), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
};
export const PUT: APIRoute = async ({ request, params }) => {
const body = await request.json();
const updated = await db.user.update({ where: { id: params.id }, data: body });
return Response.json(updated); // shorthand in newer Astro
};
export const DELETE: APIRoute = async ({ params }) => {
await db.user.delete({ where: { id: params.id } });
return new Response(null, { status: 204 });
};
// Prerender: false means this endpoint is always server-rendered
export const prerender = false;
Why
Astro server endpoints are plain Response objects — they follow the Web Fetch API standard. Each exported HTTP method name becomes a handler. They run server-side only and have access to locals set by middleware.
Gotchas
- Endpoint files must have output: 'server' or 'hybrid' in astro.config.mjs — or export prerender = false
- Response.json() is available in Astro 4.0+ — use new Response(JSON.stringify(), { headers }) for older versions
- CORS must be set manually — add Access-Control-Allow-Origin headers in the response
- POST body parsing: request.json(), request.formData(), request.text() depending on content type
Code Snippets
Webhook endpoint with signature verification
// src/pages/api/webhook.ts
export const POST: APIRoute = async ({ request }) => {
const signature = request.headers.get('x-signature');
const body = await request.text();
if (!verify(body, signature)) {
return new Response('Unauthorized', { status: 401 });
}
await processWebhook(JSON.parse(body));
return new Response('OK', { status: 200 });
};Context
When building REST API endpoints within an Astro SSR application
Revisions (0)
No revisions yet.