#Build an API with Astro Actions
4 messages · Page 1 of 1 (latest)
Hi @stone crow. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Both options are valid, but they serve different purposes. Here's a breakdown to help you decide:
Astro Actions
Actions are purpose-built for type-safe backend communication within an Astro project. They offer:
- Automatic input validation via Zod schemas
- Standardized error handling with
ActionError - Type-safe client calls — no manual
fetch()needed - Support for both JSON and form data (
accept: 'form')
A basic action looks like this:
// src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
getGreeting: defineAction({
input: z.object({
name: z.string(),
}),
handler: async (input) => {
return `Hello, ${input.name}!`;
}
})
}
You can call it from the client:
import { actions } from 'astro:actions';
const { data, error } = await actions.getGreeting({ name: "Houston" });
Security consideration
Actions are public endpoints accessible by their name (e.g., /_actions/blog.like). You must apply the same authorization checks you would for any API endpoint. You can authorize from within the handler using context.locals, or gate requests from middleware using getActionContext(). [Security]
Custom HTTP Endpoints
Endpoints are better suited when you need:
- Full control over HTTP methods (
GET,POST,DELETE, etc.) - Custom response headers, status codes, or binary responses (e.g., images)
- A more traditional REST API structure
Recommendation for your use case
Since your project is frontend + backend all inside Astro and you value simplified definition, error handling, and input validation, Astro Actions are a strong fit. They are designed exactly for seamless client-server communication within an Astro project.