api-design-restful

RESTful API design patterns, error handling, and documentation

16 stars

Best use case

api-design-restful is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

RESTful API design patterns, error handling, and documentation

Teams using api-design-restful should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/api-design-restful/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/backend/api-design-restful/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/api-design-restful/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How api-design-restful Compares

Feature / Agentapi-design-restfulStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

RESTful API design patterns, error handling, and documentation

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# RESTful API Design

## Core Principles

1. **Resource-Oriented** - URLs represent nouns, not verbs
2. **Stateless** - Each request contains all necessary information
3. **Consistent** - Use standard HTTP methods and status codes
4. **Versioned** - Support API evolution without breaking clients

## URL Structure

```
# Collection resources
GET    /api/v1/users           # List users
POST   /api/v1/users           # Create user

# Individual resources
GET    /api/v1/users/:id       # Get user
PUT    /api/v1/users/:id       # Replace user
PATCH  /api/v1/users/:id       # Update user
DELETE /api/v1/users/:id       # Delete user

# Nested resources
GET    /api/v1/users/:id/posts # User's posts
POST   /api/v1/users/:id/posts # Create post for user

# Filtering, sorting, pagination
GET    /api/v1/users?status=active&sort=-createdAt&page=2&limit=20
```

## Response Structure

### Success Response
```typescript
interface SuccessResponse<T> {
  success: true;
  data: T;
  meta?: {
    page?: number;
    limit?: number;
    total?: number;
    totalPages?: number;
  };
}

// Example
{
  "success": true,
  "data": { "id": "123", "name": "John" },
  "meta": { "requestId": "abc-123" }
}
```

### Error Response
```typescript
interface ErrorResponse {
  success: false;
  error: {
    code: string;        // Machine-readable code
    message: string;     // Human-readable message
    details?: unknown;   // Field-level errors
  };
}

// Example
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request body",
    "details": {
      "email": "Invalid email format",
      "age": "Must be a positive number"
    }
  }
}
```

## HTTP Status Codes

```typescript
// Success
200 OK              // Successful GET, PUT, PATCH
201 Created         // Successful POST
204 No Content      // Successful DELETE

// Client Errors
400 Bad Request     // Validation errors
401 Unauthorized    // Missing/invalid auth
403 Forbidden       // Insufficient permissions
404 Not Found       // Resource doesn't exist
409 Conflict        // Duplicate/state conflict
422 Unprocessable   // Semantic errors
429 Too Many Reqs   // Rate limited

// Server Errors
500 Internal Error  // Unexpected server error
503 Unavailable     // Service temporarily down
```

## Express.js Implementation

```typescript
import express from 'express';

const app = express();

// Async handler wrapper
const asyncHandler = (fn: RequestHandler) => (req, res, next) =>
  Promise.resolve(fn(req, res, next)).catch(next);

// Controller
const getUsers = asyncHandler(async (req, res) => {
  const { page = 1, limit = 20, status } = req.query;
  const { users, total } = await userService.findAll({ page, limit, status });

  res.json({
    success: true,
    data: users,
    meta: { page, limit, total, totalPages: Math.ceil(total / limit) }
  });
});

// Error handler middleware
app.use((err, req, res, next) => {
  const status = err.status || 500;
  res.status(status).json({
    success: false,
    error: {
      code: err.code || 'INTERNAL_ERROR',
      message: err.message || 'Something went wrong',
      ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
    }
  });
});
```

## Validation with Zod

```typescript
import { z } from 'zod';

const createUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(2).max(100),
  role: z.enum(['user', 'admin']).default('user'),
});

// Middleware
const validate = (schema: z.ZodSchema) => (req, res, next) => {
  const result = schema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({
      success: false,
      error: {
        code: 'VALIDATION_ERROR',
        message: 'Invalid request body',
        details: result.error.flatten().fieldErrors
      }
    });
  }
  req.body = result.data;
  next();
};

app.post('/users', validate(createUserSchema), createUser);
```

## Authentication

```typescript
// JWT middleware
const authenticate = asyncHandler(async (req, res, next) => {
  const token = req.headers.authorization?.replace('Bearer ', '');
  if (!token) {
    throw new ApiError(401, 'UNAUTHORIZED', 'Missing auth token');
  }

  const payload = await verifyToken(token);
  req.user = payload;
  next();
});

// Role-based authorization
const authorize = (...roles: string[]) => (req, res, next) => {
  if (!roles.includes(req.user.role)) {
    throw new ApiError(403, 'FORBIDDEN', 'Insufficient permissions');
  }
  next();
};

app.delete('/users/:id', authenticate, authorize('admin'), deleteUser);
```

## Rate Limiting

```typescript
import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100,
  standardHeaders: true,
  legacyHeaders: false,
  handler: (req, res) => {
    res.status(429).json({
      success: false,
      error: {
        code: 'RATE_LIMITED',
        message: 'Too many requests, please try again later'
      }
    });
  }
});

app.use('/api/', limiter);
```

## Best Practices

1. **Use plural nouns** for resources (`/users` not `/user`)
2. **Version your API** from day one (`/api/v1/`)
3. **Return appropriate status codes** for every response
4. **Include request IDs** in responses for debugging
5. **Document with OpenAPI/Swagger** specification
6. **Implement pagination** for list endpoints
7. **Use consistent error format** across all endpoints
8. **Log all requests** with correlation IDs

Related Skills

mongodb-schema-design

16
from diegosouzapw/awesome-omni-skill

Master MongoDB schema design and data modeling patterns. Learn embedding vs referencing, relationships, normalization, and schema evolution. Use when designing databases, normalizing data, or optimizing queries.

domain-driven-design

16
from diegosouzapw/awesome-omni-skill

Plan and route Domain-Driven Design work from strategic modeling to tactical implementation and evented architecture patterns.

data-designer

16
from diegosouzapw/awesome-omni-skill

Generate high-quality synthetic datasets using statistical samplers and Claude's native LLM capabilities. Use when users ask to create synthetic data, generate datasets, create fake/mock data, generate test data, training data, or any data generation task. Supports CSV, JSON, JSONL, Parquet output. Adapted from NVIDIA NeMo DataDesigner (Apache 2.0).

analytics-design

16
from diegosouzapw/awesome-omni-skill

Design data analysis from purpose clarification to visualization. Use when analyzing data, exploring BigQuery schemas, building queries, or creating Looker Studio reports.

---name: aav-vector-design-agent

16
from diegosouzapw/awesome-omni-skill

description: AI-powered adeno-associated virus (AAV) vector design for gene therapy including capsid engineering, promoter selection, and tropism optimization.

Schema Design

16
from diegosouzapw/awesome-omni-skill

Migration-ready database schema design with normalization and indexing strategies

database-design

16
from diegosouzapw/awesome-omni-skill

Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases.

asyncapi-design

16
from diegosouzapw/awesome-omni-skill

Event-driven API specification with AsyncAPI 3.0 for message-based architectures

API Test Design

16
from diegosouzapw/awesome-omni-skill

Strategies for designing comprehensive API tests including contract testing, integration testing, and performance testing

api-rest-design

16
from diegosouzapw/awesome-omni-skill

Apply when designing RESTful APIs, defining endpoints, HTTP methods, status codes, and response formats.

api-portal-design

16
from diegosouzapw/awesome-omni-skill

API documentation and developer portal design

api-first-design

16
from diegosouzapw/awesome-omni-skill

**API FIRST DESIGN**: 'API 만들어', 'API 설계', '엔드포인트', 'REST', 'Swagger', 'OpenAPI', 'DTO', 'CRUD' 요청 시 자동 발동. *.controller.ts/*.dto.ts/routes/** 파일 작업 시 자동 적용. Contract-First, 표준 응답 포맷, 타입 자동 생성.