원클릭으로
api-design
Use this skill when designing or implementing REST APIs, endpoints, routes, or controllers.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use this skill when designing or implementing REST APIs, endpoints, routes, or controllers.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
This skill should be used when the user asks to "run glab commands", "create a GitLab issue", "create a merge request", "check pipeline status", "manage GitLab projects", "create a release", or mentions glab, GitLab CLI, gitlab-cli, merge request, MR, GitLab pipeline, GitLab CI, GitLab issue keys, or gitlab operations via the command line.
Use this skill when the user asks about Conductor concepts, workflow patterns, track lifecycle, plan structures, or context-driven development principles. Also activate when working with conductor/ directory files or when implementing tasks following TDD and verification protocols.
This skill should be used when the user asks to "run acli jira commands", "create a Jira issue", "search Jira issues", "manage Jira projects", "transition Jira status", "check jira issue", "consistent with jira issue", or mentions ACLI, Atlassian CLI, Jira CLI, Jira issue keys (e.g. KAN-1, PROJ-123), or jira workitem/project/board/sprint operations via the command line.
Use this skill when working with Java code, Optional handling, CompletableFuture, records, sealed classes, or virtual threads.
Use this skill when writing tests, implementing TDD, or setting up test infrastructure.
Use this skill when working with TypeScript code, type definitions, interfaces, generics, or async patterns.
| name | api-design |
| description | Use this skill when designing or implementing REST APIs, endpoints, routes, or controllers. |
| version | 1.0.0 |
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