alepha@docs:~/docs/reference/primitives$
cat $action.md | pretty
2 min read

#$action

#Import

typescript
1import { $action } from "alepha/server";

#Overview

Creates a server action primitive for defining type-safe HTTP endpoints.

Server actions are the core building blocks for REST APIs in Alepha, providing declarative HTTP endpoints with full type safety, automatic validation, and OpenAPI documentation.

Key Features

  • Full TypeScript inference for request/response types
  • Automatic schema validation using Zod
  • An explicit method and path on every action, no convention to remember
  • Direct invocation (run()) or HTTP requests (fetch())
  • Built-in authentication and authorization support
  • Automatic content-type handling (JSON, form-data, plain text)

URL Generation

Important: All $action paths are automatically prefixed with /api.

ts
1$action({ method: "GET", path: "/users" })     // → GET /api/users2$action({ method: "GET", path: "/users/:id" }) // → GET /api/users/:id3$action({ method: "POST", path: "/hello" })    // → POST /api/hello

This prefix is configurable via the serverApiOptions atom (alepha.store.mut(serverApiOptions, (o) => ({ ...o, prefix: "/v1" }))). method and path are both required: a read declares method: "GET", and renaming the property never moves the URL.

Common Use Cases

  • CRUD operations with type safety
  • File upload and download endpoints
  • Microservice communication

#Options

Option Type Required Description
name string No Name of the action
group string No Group actions together
path string Yes Pathname of the route, below the API prefix (/api by default)
method RouteMethod Yes The route method
schema TConfig No The config schema of the route
description string No A short description of the action
disabled boolean No Disable the route
use TUse No Middlewares wrapping the handler, outermost first
errors TErrors No The errors this action answers with: $error constants or built-in HttpError classes (NotFoundError)
timeout DurationLike | false No How long the action may run before it answers 503 with a TimeoutError
handler ServerActionHandler<TConfig, TUse> Yes Main route handler

#Examples

ts
 1class UserController { 2  getUsers = $action({ 3    method: "GET", 4    path: "/users", 5    schema: { 6      query: z.object({ 7        page: z.number().default(1).optional(), 8        limit: z.number().default(10).optional() 9      }),10      response: z.object({11        users: z.array(z.object({12          id: z.text(),13          name: z.text(),14          email: z.text()15        })),16        total: z.number()17      })18    },19    handler: async ({ query }) => {20      const users = await this.userService.findUsers(query);21      return { users: users.items, total: users.total };22    }23  });24 25  createUser = $action({26    method: "POST",27    path: "/users",28    schema: {29      body: z.object({30        name: z.text(),31        email: z.text({ format: "email" })32      }),33      response: z.object({ id: z.text(), name: z.text() })34    },35    handler: async ({ body }) => {36      return await this.userService.create(body);37    }38  });39}