Endpoints & API Routes
A route that returns data, not a page
Section titled “A route that returns data, not a page”Not every route renders HTML. A file in src/pages/ with a .ts (or .js) extension is an API endpoint: instead of a template, it exports functions named after HTTP methods (GET, POST, PUT, DELETE) that each return a standard Response.
import type { APIRoute } from 'astro';
export const GET: APIRoute = () => { return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, });};GET /api/health now returns JSON. The APIRoute type gives you a typed context argument and a Response return — the same web-standard shape as everywhere else in Astro.
Reading params and the body
Section titled “Reading params and the body”The handler receives a context with the request, params, cookies, and more:
import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params }) => { const user = await db.users.find(params.id); // [id] from the path if (!user) return new Response('Not found', { status: 404 }); return Response.json(user); // shorthand JSON response};
export const POST: APIRoute = async ({ request }) => { const body = await request.json(); // parse the request body const created = await db.users.create(body); return Response.json(created, { status: 201 });};flowchart LR req["GET or POST /api/..."] --> handler["exported handler (GET / POST / ...)"] handler --> read["read params, request body, cookies"] read --> resp["return a Response (JSON, file, status)"]
Static vs on-demand endpoints
Section titled “Static vs on-demand endpoints”Like pages, endpoints can be built once or run per request:
- Static — with
output: 'static', aGETendpoint runs at build time and itsResponsebody is written to a file. Great for generating arss.xml, asitemap, or a static JSON API that doesn’t change per request. (Static endpoints only supportGET.) - On-demand — add
export const prerender = false(and an adapter) to run the endpoint per request, enablingPOST/PUT/DELETE, request bodies, and live data.
// A dynamic endpoint that handles form posts:export const prerender = false;Endpoints vs Actions
Section titled “Endpoints vs Actions”Both run server code, but they solve different problems:
- An endpoint is a raw HTTP route you design yourself — you own the URL, method, status codes, and response shape. Reach for it for webhooks, third-party integrations, file downloads, or a public REST/JSON API.
- An Action (next lesson) is a type-safe function you call from your own client code with automatic input validation — no URL or
Responseplumbing. Reach for it for your app’s own mutations and forms.
Rule of thumb: public/external contract → endpoint; internal app logic called from your own frontend → Action.