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 property | What it holds |
|---|---|
request | The request: method, headers, body |
params | Parameters, if the file is named like [id].ts |
url | The request address |
cookies | Request 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.