Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

API endpoints

An endpoint is an address that returns data instead of an HTML page: JSON, text, a file. In Astro it is a .js or .ts file in src/pages/ that exports functions named after HTTP methods: GET, POST and others. Each function returns a standard Response object.

A static endpoint

Let us make a list of posts in JSON format. Create src/pages/api/posts.json.ts:

// src/pages/api/posts.json.ts
import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';
 
export const GET: APIRoute = async () => {
  const posts = await getCollection('blog');
  const list = posts.map((post) => ({
    id: post.id,
    title: post.data.title,
  }));
 
  return new Response(JSON.stringify(list), {
    headers: { 'Content-Type': 'application/json' },
  });
};

Open http://localhost:4321/api/posts.json and the browser shows an array of posts. The .json extension in the file name becomes part of the address. In static mode Astro runs the function during the build and saves the result as the file dist/api/posts.json.

An on-demand endpoint

To accept data from visitors, the endpoint has to run on the server, which needs the adapter from the previous lesson. Create src/pages/api/likes.ts:

// src/pages/api/likes.ts
import type { APIRoute } from 'astro';
 
export const prerender = false;
 
let likes = 0;
 
export const POST: APIRoute = async ({ request }) => {
  const body = await request.json();
  likes += body.count ?? 1;
 
  return Response.json({ likes });
};

The function reads the request body, increases the counter and answers with JSON. Response.json() is a shorthand for a response with the Content-Type: application/json header. The counter lives in server memory and resets on restart; a real project keeps it in a database.

Calling it from the browser

An endpoint is called with ordinary fetch(), for example from the React island LikeButton.jsx:

// src/components/LikeButton.jsx
async function sendLike() {
  const response = await fetch('/api/likes', {
    method: 'POST',
    body: JSON.stringify({ count: 1 }),
  });
  const data = await response.json();
  console.log(data.likes);
}

After each call the browser console shows the new total number of likes.

What the function receives

Context propertyWhat it holds
requestThe request: method, headers, body
paramsParameters, if the file is named like [id].ts
urlThe request address
cookiesRequest and response cookies

Common mistake

People create an endpoint with POST on a static site without prerender = false. During the build Astro calls only GET, so POST does not work on the deployed site. Always mark endpoints that accept data with export const prerender = false and add an adapter.

Thanks for reading!

Donate to the site — we work hard for you.