API Designer Skill
Role
Backend developer who designs and implements RESTful APIs
API Design Principles
RESTful Rules
| Method | Purpose | Path Pattern |
|---|---|---|
| GET | Retrieve | /api/resources, /api/resources/:id |
| POST | Create | /api/resources |
| PATCH | Partial update | /api/resources/:id |
| PUT | Full replace | /api/resources/:id |
| DELETE | Delete | /api/resources/:id |
Response Format
typescript1// Success 2{ data: T } 3{ data: T[], total?: number } 4 5// Error 6{ error: string, details?: unknown }
HTTP Status Codes
| Code | Purpose |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad request |
| 404 | Not found |
| 500 | Server error |
Implementation Order
1. Type Definition (packages/shared)
typescript1// packages/shared/src/index.ts 2export type CreateFeatureRequest = { 3 name: string; 4 description?: string; 5}; 6 7export type FeatureResponse = { 8 id: string; 9 name: string; 10 description: string | null; 11 createdAt: string; 12};
2. DB Schema (if needed)
typescript1// packages/db/src/schema.ts 2export const features = sqliteTable('features', { 3 id: text('id').primaryKey(), 4 name: text('name').notNull(), 5 description: text('description'), 6 createdAt: text('created_at').notNull(), 7});
3. Route Implementation
typescript1// apps/server/src/routes/features.ts 2import { Router } from 'express'; 3import { db } from '@local-review/db'; 4import { features } from '@local-review/db/schema'; 5import { nanoid } from 'nanoid'; 6 7const router = Router(); 8 9// GET /api/features 10router.get('/', async (req, res) => { 11 try { 12 const result = await db.select().from(features); 13 res.json(result); 14 } catch (error) { 15 res.status(500).json({ error: 'Failed to fetch features' }); 16 } 17}); 18 19// POST /api/features 20router.post('/', async (req, res) => { 21 try { 22 const { name, description } = req.body; 23 24 if (!name) { 25 return res.status(400).json({ error: 'Name is required' }); 26 } 27 28 const newFeature = { 29 id: nanoid(), 30 name, 31 description: description ?? null, 32 createdAt: new Date().toISOString(), 33 }; 34 35 await db.insert(features).values(newFeature); 36 res.status(201).json(newFeature); 37 } catch (error) { 38 res.status(500).json({ error: 'Failed to create feature' }); 39 } 40}); 41 42export default router;
4. Register Route
typescript1// apps/server/src/index.ts 2import featuresRouter from './routes/features'; 3app.use('/api/features', featuresRouter);
5. Frontend API Client
typescript1// apps/web/src/lib/api.ts 2export const featureApi = { 3 list: () => fetchJson<FeatureResponse[]>('/api/features'), 4 create: (data: CreateFeatureRequest) => 5 fetchJson<FeatureResponse>('/api/features', { 6 method: 'POST', 7 body: JSON.stringify(data), 8 }), 9};
Existing API Reference
Current project API structure:
GET /api/git/branches- Branch listGET/POST /api/sessions- Session CRUDGET/POST /api/sessions/:id/comments- CommentsPATCH /api/sessions/:id/files/*/status- File status