Routing & SSR: API endpoints in Astro

Join the AI Workshop to learn more about AI and how it can be applied to web development. Next cohort February 1st, 2026

The AI-first Web Development BOOTCAMP cohort starts February 24th, 2026. 10 weeks of intensive training and hands-on projects.


One interesting feature we can use in Astro with SSR enabled is API endpoints.

To create an endpoint you add a file ending with .json.js in the src/pages folder, and it will be an API route with GET, POST and the other HTTP methods.

For example create this file:

src/pages/todos.json.js

You can define a GET API endpoint by exporting a GET function:

export const GET = async ({ params, request }) => {

}

You can return some JSON now by returning a new Response object with a JSON response:

export const GET = async ({ params, request }) => {
  return new Response(JSON.stringify([
    'Buy the milk', 
    'Write a blog post'
  ]))
}

Hit http://localhost:4321/todos.json to see the JSON returned from your API endpoint:

I returned a hardcoded set of data, but I could have hooked a database here.

You can inspect any data received in the URL using the params parameter (only in GET requests), and the request data in request.

For example you can inspect the body using await request.json() and header data using request.headers.

Just as we did a GET endpoint, we can add an HTTP POST endpoint using a POST function

export const POST = async ({ request }) => {

}

For example we can console.log() on the server any data coming in the request headers and the request body:

export const POST = async ({ request }) => {
  console.log(request.headers)
  console.log(await request.json())
  return new Response()
}

You could use this to add data to a database, handle form submissions, and what not.

Lessons in this unit:

0: Introduction
1: Dynamic routing
2: SSR in Astro
3: ▶︎ API endpoints in Astro
4: Prerendering a component in an SSR page
5: Set cookie and redirect
6: Render different HTML based on HTTP method
7: Decide to render a partial or not dynamically in Astro
8: Fetching data from the network