From conductor
Guides RESTful API design and implementation: resource naming, HTTP methods, URL patterns, error responses, versioning, and core principles.
npx claudepluginhub rbarcante/claude-conductor --plugin conductorThis skill uses the workspace's default tool permissions.
Guidance for designing and implementing RESTful APIs. Covers URL conventions, HTTP methods, error handling, versioning, and common patterns.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
Guidance for designing and implementing RESTful APIs. Covers URL conventions, HTTP methods, error handling, versioning, and common patterns.
# Good - plural nouns, lowercase, hyphens
GET /api/v1/users
GET /api/v1/users/:id
GET /api/v1/users/:id/orders
GET /api/v1/order-items
# Avoid - verbs, mixed case, underscores
GET /api/v1/getUsers
GET /api/v1/User/:id
POST /api/v1/create_order
| Method | Purpose | Idempotent | Request Body |
|---|---|---|---|
| GET | Read resource(s) | Yes | No |
| POST | Create resource | No | Yes |
| PUT | Replace resource | Yes | Yes |
| PATCH | Partial update | Yes | Yes |
| DELETE | Remove resource | Yes | No |
# Collection operations
GET /api/v1/users # List all
POST /api/v1/users # Create one
# Single resource
GET /api/v1/users/:id # Get one
PUT /api/v1/users/:id # Replace one
PATCH /api/v1/users/:id # Update one
DELETE /api/v1/users/:id # Delete one
# Nested resources
GET /api/v1/users/:id/orders
POST /api/v1/users/:id/orders
# Actions (when REST doesn't fit)
POST /api/v1/users/:id/activate
POST /api/v1/orders/:id/cancel
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
],
"requestId": "req_abc123"
}
}
# Success
200 OK - Successful GET, PUT, PATCH, DELETE
201 Created - Successful POST creating resource
204 No Content - Successful DELETE with no body
# Client Errors
400 Bad Request - Invalid request syntax/body
401 Unauthorized - Missing/invalid authentication
403 Forbidden - Authenticated but not authorized
404 Not Found - Resource doesn't exist
409 Conflict - Resource state conflict
422 Unprocessable - Validation errors
# Server Errors
500 Internal Error - Unexpected server error
502 Bad Gateway - Upstream service error
503 Unavailable - Service temporarily down
// Error class hierarchy
class ApiError extends Error {
constructor(
public code: string,
public message: string,
public statusCode: number,
public details?: unknown[]
) {
super(message);
}
}
class ValidationError extends ApiError {
constructor(details: { field: string; message: string }[]) {
super('VALIDATION_ERROR', 'Request validation failed', 422, details);
}
}
class NotFoundError extends ApiError {
constructor(resource: string, id: string) {
super('NOT_FOUND', `${resource} with id ${id} not found`, 404);
}
}
// Global error handler
function errorHandler(err: Error, req: Request, res: Response) {
if (err instanceof ApiError) {
return res.status(err.statusCode).json({
error: {
code: err.code,
message: err.message,
details: err.details,
requestId: req.id
}
});
}
// Unexpected error - log and return generic message
logger.error('Unhandled error', { error: err, requestId: req.id });
return res.status(500).json({
error: {
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred',
requestId: req.id
}
});
}
GET /api/v1/users
GET /api/v2/users
// Version-specific routers
const v1Router = Router();
const v2Router = Router();
v1Router.get('/users', getUsersV1);
v2Router.get('/users', getUsersV2);
app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);
// Deprecation header
res.setHeader('Deprecation', 'true');
res.setHeader('Sunset', 'Sat, 01 Jan 2025 00:00:00 GMT');
res.setHeader('Link', '</api/v2/users>; rel="successor-version"');
// Request
GET /api/v1/users?limit=20&cursor=eyJpZCI6MTIzfQ
// Response
{
"data": [...],
"pagination": {
"hasMore": true,
"nextCursor": "eyJpZCI6MTQzfQ",
"prevCursor": "eyJpZCI6MTAzfQ"
}
}
// Request
GET /api/v1/users?page=2&limit=20
// Response
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 150,
"totalPages": 8
}
}
// Single resource
res.status(200).json({ data: user });
// Collection
res.status(200).json({
data: users,
pagination: { ... }
});
// Created resource
res.status(201).json({ data: newUser });
// No content
res.status(204).send();
# Filtering
GET /api/v1/users?status=active&role=admin
# Sorting
GET /api/v1/users?sort=createdAt:desc,name:asc
# Field selection
GET /api/v1/users?fields=id,name,email