| name | api-designing |
| description | Design consistent RESTful API endpoints, request/response formats, and error handling patterns. Use when creating new API routes, designing API structure, planning request/response schemas, or establishing API conventions. Triggers on requests like "design an API for", "create API endpoints", "plan the API structure", "design the response format", or "API conventions". |
API Designing
Design consistent RESTful APIs for this Next.js application.
Process
- Identify resources - What entities does the API manage?
- Define operations - CRUD and custom actions
- Design endpoints - URL structure and methods
- Specify schemas - Request/response formats
- Plan error handling - Consistent error responses
RESTful Conventions
URL Structure
/api/[resource] # Collection
/api/[resource]/[id] # Individual resource
/api/[resource]/[id]/[sub] # Nested resource
HTTP Methods
| Method | Purpose | Idempotent |
|---|
| GET | Retrieve resource(s) | Yes |
| POST | Create resource | No |
| PUT | Replace resource | Yes |
| PATCH | Partial update | Yes |
| DELETE | Remove resource | Yes |
Existing Project Patterns
Admin routes follow this structure:
/admin/api/articles GET (list), POST (create)
/admin/api/articles/[id] GET, PUT, DELETE
/admin/api/tags GET, POST
/admin/api/media GET, POST
/admin/api/users GET, POST
/admin/api/users/[id]/approve POST (action)
Request Schemas
List Endpoints (GET collection)
Query parameters:
?page=1 # Pagination
?limit=10 # Items per page
?sort=created_at # Sort field
?order=desc # Sort direction
?status=published # Filtering
?search=query # Text search
Create/Update (POST/PUT)
{
title: string;
body: string;
slug?: string;
published?: boolean;
media_id?: number;
}
Response Schemas
Success Responses
Single resource:
{
success: true,
data: {
id: number;
title: string;
}
}
Collection:
{
success: true,
data: Resource[],
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
}
}
Action result:
{
success: true,
message: "Article published successfully"
}
Error Responses
{
success: false,
error: "Validation failed",
details: {
title: "Title is required",
slug: "Slug already exists"
}
}
{
success: false,
error: "Authentication required"
}
{
success: false,
error: "Admin access required"
}
{
success: false,
error: "Article not found"
}
{
success: false,
error: "An unexpected error occurred"
}
Implementation Pattern
import { NextRequest, NextResponse } from "next/server";
import { requireEditor } from "@/lib/api-auth";
import { getDb } from "@/lib/db";
export async function GET(request: NextRequest) {
const auth = await requireEditor();
if (!auth.authorized) return auth.response;
try {
const db = await getDb();
const { searchParams } = new URL(request.url);
const page = parseInt(searchParams.get("page") || "1");
const limit = parseInt(searchParams.get("limit") || "10");
const offset = (page - 1) * limit;
const items = await db.prepare(`
SELECT * FROM resources
ORDER BY created_at DESC
LIMIT ? OFFSET ?
`).(limit, offset).();
{ total } = db.().();
.({
: ,
: items.,
: {
page,
limit,
total,
: .(total / limit),
},
});
} (error) {
.(, error);
.(
{ : , : },
{ : }
);
}
}
Validation
Validate at API boundaries:
function validateArticle(data: unknown): { valid: boolean; errors?: Record<string, string> } {
const errors: Record<string, string> = {};
if (!data || typeof data !== 'object') {
return { valid: false, errors: { _: 'Invalid request body' } };
}
const { title, body, slug } = data as Record<string, unknown>;
if (!title || typeof title !== 'string') {
errors.title = 'Title is required';
}
if (!body || typeof body !== 'string') {
errors.body = 'Body is required';
}
if (slug && typeof slug !== 'string') {
errors.slug = 'Slug must be a string';
}
return Object.keys(errors).length ? { valid: false, errors } : { valid: };
}
Output
Provide API design deliverables:
- Endpoint specifications (URL, method, auth)
- Request schema (body, query params)
- Response schema (success, error)
- Example implementation code