Build or update the BlueBubbles external channel plugin for Moltbot (extension package, REST...
npx skills add turnerworks/agent-skills
Or install specific skill: npx add-skill https://github.com/turnerworks/agent-skills/tree/main/turnerworks-api-design
# Description
Guidelines for building well-structured REST APIs following TurnerWorks standards
# SKILL.md
name: TurnerWorks API Design
version: 1.0.0
description: Guidelines for building well-structured REST APIs following TurnerWorks standards
author: TurnerWorks
tags: [api, rest, typescript, nextjs, turnerworks]
TurnerWorks API Design Skill
This skill provides comprehensive guidelines for designing and implementing REST APIs that follow TurnerWorks coding standards and best practices.
Overview
When building APIs for TurnerWorks projects, always follow these principles:
- Type safety with TypeScript
- Consistent error handling
- RESTful conventions
- Clear documentation
- Testable architecture
Instructions
1. Project Structure
Organize API routes using Next.js App Router conventions:
app/
api/
[resource]/
route.ts # GET (list), POST (create)
[id]/
route.ts # GET (single), PUT/PATCH, DELETE
lib/
validators/ # Zod schemas
services/ # Business logic
types/ # TypeScript interfaces
2. TypeScript Types
Define reusable types for all API interactions:
// types/api.ts
export interface ApiResponse<T> {
success: boolean;
data?: T;
error?: {
code: string;
message: string;
details?: Record<string, string[]>;
};
meta?: {
page?: number;
limit?: number;
total?: number;
};
}
export interface PaginationParams {
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
3. Request Validation
Use Zod for runtime validation:
// validators/resource.ts
import { z } from 'zod';
export const createResourceSchema = z.object({
name: z.string().min(1).max(255),
description: z.string().optional(),
status: z.enum(['draft', 'active', 'archived']).default('draft'),
});
export type CreateResourceInput = z.infer<typeof createResourceSchema>;
4. Route Handler Pattern
Follow this consistent pattern for all route handlers:
// app/api/resources/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { createResourceSchema } from '@/lib/validators/resource';
import { ResourceService } from '@/lib/services/resource';
import type { ApiResponse } from '@/lib/types/api';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const validated = createResourceSchema.safeParse(body);
if (!validated.success) {
return NextResponse.json<ApiResponse<never>>({
success: false,
error: {
code: 'VALIDATION_ERROR',
message: 'Invalid request data',
details: validated.error.flatten().fieldErrors,
},
}, { status: 400 });
}
const resource = await ResourceService.create(validated.data);
return NextResponse.json<ApiResponse<typeof resource>>({
success: true,
data: resource,
}, { status: 201 });
} catch (error) {
console.error('[API] POST /resources error:', error);
return NextResponse.json<ApiResponse<never>>({
success: false,
error: {
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred',
},
}, { status: 500 });
}
}
5. Error Codes
Use standardized error codes:
| Code | HTTP Status | Description |
|---|---|---|
| VALIDATION_ERROR | 400 | Request validation failed |
| UNAUTHORIZED | 401 | Authentication required |
| FORBIDDEN | 403 | Insufficient permissions |
| NOT_FOUND | 404 | Resource not found |
| CONFLICT | 409 | Resource already exists |
| INTERNAL_ERROR | 500 | Server error |
6. Testing Requirements
Every API endpoint must have:
- Unit tests for validators
- Integration tests for route handlers
- Error scenario coverage
// __tests__/api/resources.test.ts
import { POST } from '@/app/api/resources/route';
describe('POST /api/resources', () => {
it('creates resource with valid data', async () => {
const request = new Request('http://localhost/api/resources', {
method: 'POST',
body: JSON.stringify({ name: 'Test Resource' }),
});
const response = await POST(request as any);
const data = await response.json();
expect(response.status).toBe(201);
expect(data.success).toBe(true);
});
it('returns validation error for invalid data', async () => {
const request = new Request('http://localhost/api/resources', {
method: 'POST',
body: JSON.stringify({ name: '' }),
});
const response = await POST(request as any);
const data = await response.json();
expect(response.status).toBe(400);
expect(data.error.code).toBe('VALIDATION_ERROR');
});
});
Best Practices
- Always validate input - Never trust client data
- Use consistent response format - All responses follow ApiResponse
- Log errors appropriately - Include context but never sensitive data
- Handle edge cases - Empty arrays, null values, missing optional fields
- Version APIs when needed - Use
/api/v2/for breaking changes - Document with OpenAPI - Generate specs from Zod schemas
Related Skills
- turnerworks-database-design
- turnerworks-authentication
- turnerworks-testing
# README.md
agent-skills
TurnerWorks Agent Skills - Reusable SKILL.md files for AI coding assistants (Claude, Cursor, Windsurf, etc.)
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.