From one
Create API routes in One framework. Use when building HTTP endpoints, webhooks, REST APIs, or server-side logic with +api.ts files.
How this skill is triggered — by the user, by Claude, or both
Slash command
/one:one-api-routesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Official docs: [Routing](https://onestack.dev/docs/routing)
Official docs: Routing
API routes are server-only HTTP endpoints. Name files with the +api.ts suffix.
app/
api/
route+api.ts GET /api
users/
route+api.ts GET/POST /api/users
[id]+api.ts GET/PUT/DELETE /api/users/:id
webhooks/
stripe+api.ts POST /api/webhooks/stripe
Export named functions for HTTP methods:
// app/api/health+api.ts
export function GET() {
return Response.json({ status: 'ok' })
}
// app/api/users/route+api.ts
export async function GET(request: Request) {
const users = await db.users.findMany()
return Response.json(users)
}
export async function POST(request: Request) {
const body = await request.json()
const user = await db.users.create(body)
return Response.json(user, { status: 201 })
}
// app/api/users/[id]+api.ts
export async function GET(request: Request, { params }: { params: { id: string } }) {
const user = await db.users.find(params.id)
if (!user) {
return Response.json({ error: 'Not found' }, { status: 404 })
}
return Response.json(user)
}
export async function PUT(request: Request, { params }: { params: { id: string } }) {
const body = await request.json()
const user = await db.users.update(params.id, body)
return Response.json(user)
}
export async function DELETE(request: Request, { params }: { params: { id: string } }) {
await db.users.delete(params.id)
return new Response(null, { status: 204 })
}
A default export catches all HTTP methods:
// app/api/proxy+api.ts
export default async function handler(request: Request) {
// handles GET, POST, PUT, DELETE, etc.
return fetch(`https://upstream.api${new URL(request.url).pathname}`, {
method: request.method,
headers: request.headers,
body: request.body,
})
}
Standard Web API Request object:
export async function POST(request: Request) {
// JSON body
const json = await request.json()
// Form data
const form = await request.formData()
// Raw text
const text = await request.text()
// Query params
const url = new URL(request.url)
const q = url.searchParams.get('q')
// Headers
const auth = request.headers.get('Authorization')
}
Standard Web API Response object:
// JSON
return Response.json({ data: 'value' })
// with status
return Response.json({ error: 'bad request' }, { status: 400 })
// with headers
return new Response(JSON.stringify(data), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=3600',
},
})
// redirect
return Response.redirect('/login', 302)
// no content
return new Response(null, { status: 204 })
Use Endpoint type for typed params:
import type { Endpoint } from 'one'
export type MyEndpoint = Endpoint<'/api/users/[id]'>
export async function GET(
request: Request,
{ params }: { params: MyEndpoint['params'] }
) {
// params.id is typed
}
Or use createAPIRoute:
import { createAPIRoute } from 'one'
export const GET = createAPIRoute<'/api/users/[id]'>(
async (request, { params }) => {
return Response.json({ id: params.id })
}
)
async function requireAuth(request: Request) {
const token = request.headers.get('Authorization')?.replace('Bearer ', '')
if (!token) {
throw Response.json({ error: 'Unauthorized' }, { status: 401 })
}
return verifyToken(token)
}
export async function GET(request: Request) {
const user = await requireAuth(request)
return Response.json({ user })
}
export async function POST(request: Request) {
try {
const body = await request.json()
const result = await processData(body)
return Response.json(result)
} catch (error) {
return Response.json(
{ error: error instanceof Error ? error.message : 'Internal error' },
{ status: 500 }
)
}
}
export async function GET() {
const stream = new ReadableStream({
async start(controller) {
for await (const chunk of generateChunks()) {
controller.enqueue(new TextEncoder().encode(chunk))
}
controller.close()
},
})
return new Response(stream, {
headers: { 'Content-Type': 'text/event-stream' },
})
}
+api.ts (or .js)[param] syntax as page routesnpx claudepluginhub onejs/skills --plugin oneProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.