Cossack makes it easy to build backend endpoints directly within your project. You can choose between two styles: Functional API Routes for simplicity, or Class-based API Routes for shared state and advanced logic.
All API routes should be placed in the src/pages/api/ directory.
Functional API Routes (Zero-Config)
For most use cases, you can simply export a standard Hono handler.
All Methods (default export)
If you export a function as the default, it will handle all HTTP methods for that route.
// src/pages/api/echo.ts export default (c) => { return c.json({ message: 'Echo!', method: c.req.method }); };
Specific Methods (Named exports)
You can export functions named GET, POST, PUT, DELETE, or PATCH to handle specific HTTP methods.
// src/pages/api/users.ts export const GET = (c) => { return c.json([{ id: 1, name: 'Alice' }]); }; export const POST = async (c) => { const data = await c.req.json(); // save to DB return c.json({ success: true }, 201); };
Class-based API Routes
If you need to share state between the client and server (via WebSockets) or prefer an object-oriented approach, you can extend the Cossack base class.
import { Cossack, Page } from '@cossackframework/core'; @Page({ transport: 'http' }) export default class MyApi extends Cossack { async get() { return this.c.json({ message: 'Hello from class!' }); } }
Routing Conventions
Cossack follows a standard file-based routing convention for API routes:
src/pages/api/hello.ts→/api/hellosrc/pages/api/users/index.ts→/api/userssrc/pages/api/users/[id].ts→/api/users/:id
Type Safety
You can use the CloudflareBindings type (generated by cf-typegen) to get full autocompletion for your environment bindings (D1, KV, etc.) inside your handlers.
export const GET = async (c) => { const env = c.env as CloudflareBindings; const data = await env.MY_KV.get('some-key'); return c.json({ data }); };