Ir al contenido
angel.library

Endpoints (API routes)

Un endpoint es un archivo .ts/.js dentro de src/pages que, en vez de exportar un componente .astro que renderiza HTML, exporta funciones con nombre de método HTTP (GET, POST…) que devuelven una Response. Astro lo trata como una ruta más: convive con páginas normales en la misma carpeta, solo que responde JSON, XML, una imagen o cualquier otro contenido en vez de HTML. Esta biblioteca no necesita un endpoint de búsqueda propio: Starlight genera el índice de Pagefind y el buscador de la cabecera abre su interfaz.

El nombre del archivo (menos .ts/.js) es la extensión de la URL: data.json.ts → /data.json.

pages/data.json.ts
import type { APIRoute } from "astro"
export const GET: APIRoute = async () => {
return new Response(JSON.stringify({ ok: true }), {
headers: { "Content-Type": "application/json" }
})
}
pages/api/[id].json.ts
import type { APIRoute } from "astro"
export const GET: APIRoute = async ({ params, request, url }) => {
const id = params.id
const query = url.searchParams.get("filtro")
return new Response(JSON.stringify({ id, query }))
}

Cada método HTTP es su propio export nombrado. Astro resuelve HEAD automáticamente a partir de GET.

export const POST: APIRoute = async ({ request }) => {
const body = await request.json()
return new Response(JSON.stringify({ recibido: body }), { status: 201 })
}
export const DELETE: APIRoute = async ({ params }) => {
return new Response(null, { status: 204 })
}

Igual que las páginas, una ruta dinámica ([id].json.ts) en modo estático necesita getStaticPaths() para saber qué archivos generar en build.

pages/api/[id].json.ts
export function getStaticPaths() {
return [{ params: { id: "1" } }, { params: { id: "2" } }]
}

Con output: 'server' en astro.config.mjs, o con export const prerender = false en el archivo aunque el proyecto siga en output: 'static', el endpoint corre en cada request en vez de generarse en build — necesario si depende de request (headers, body, cookies) en tiempo real. El antiguo valor output: 'hybrid' ya no forma parte de la configuración actual: el modo mixto se expresa por ruta con prerender.

pages/api/echo.ts
export const prerender = false
export const POST: APIRoute = async ({ request }) => {
const body = await request.json()
return new Response(JSON.stringify(body))
}
APIUso
export const GET/POST/...: APIRouteHandler por método HTTP
paramsSegmentos dinámicos de la URL
requestRequest completo (headers, body, method)
urlURL completa, incluyendo query params
getStaticPaths()Requerido en rutas dinámicas prerenderizadas
export const prerender = falseForzar ese endpoint a on-demand
  • En modo estático (sin prerender = false), request.body no está disponible de forma confiable — un endpoint que necesita leer el body de un POST necesita on-demand rendering.
  • Astro no valida nada del body automáticamente: sigue el mismo patrón que en cualquier boundary, request.json() + Zod antes de confiar en los datos.
  • Para lo que sería un formulario típico con validación, Server Actions suele ser menos código que un endpoint a mano.