rest-api
RESTful APIの設計・構築を支援し、CRUD操作の実装、認証追加、ページネーション、APIバージョン管理、OpenAPIドキュメント生成など、API開発に必要な機能を幅広くサポートするSkill。
📜 元の英語説明(参考)
Design and build RESTful APIs. Use when a user asks to create a REST API, design API endpoints, implement CRUD operations, add authentication to an API, handle pagination and filtering, set up API versioning, generate OpenAPI/Swagger docs, implement rate limiting, build middleware, handle file uploads, add CORS, implement HATEOAS, or structure an Express/Fastify/Koa/Flask/FastAPI backend. Covers HTTP methods, status codes, resource modeling, error handling, validation, and production deployment patterns.
🇯🇵 日本人クリエイター向け解説
RESTful APIの設計・構築を支援し、CRUD操作の実装、認証追加、ページネーション、APIバージョン管理、OpenAPIドキュメント生成など、API開発に必要な機能を幅広くサポートするSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o rest-api.zip https://jpskill.com/download/15343.zip && unzip -o rest-api.zip && rm rest-api.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15343.zip -OutFile "$d\rest-api.zip"; Expand-Archive "$d\rest-api.zip" -DestinationPath $d -Force; ri "$d\rest-api.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
rest-api.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
rest-apiフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
REST API
概要
業界の慣習に従い、本番環境グレードの RESTful API を設計および構築します。このスキルでは、リソースモデリング、HTTP セマンティクス、認証、バリデーション、ページネーション、バージョニング、ドキュメント化、エラー処理、およびセキュリティについて、Express (Node.js) と FastAPI (Python) の例を用いて説明します。
手順
ステップ 1: プロジェクトのセットアップ
Express:
npm install express cors helmet morgan compression zod jsonwebtoken bcrypt swagger-jsdoc swagger-ui-express
FastAPI:
pip install "fastapi[standard]" uvicorn sqlalchemy pydantic-settings python-jose[cryptography] passlib[bcrypt]
ステップ 2: リソースの設計
Resource Endpoint Methods
Users /api/v1/users GET, POST
User /api/v1/users/:id GET, PUT, PATCH, DELETE
User Posts /api/v1/users/:id/posts GET
Posts /api/v1/posts GET, POST
Post Comments /api/v1/posts/:id/comments GET, POST
ルール: 複数形の名詞 (/users)、URL に動詞を含めない、最大 2 段階のネスト、ケバブケース (/user-profiles)。
ステップ 3: HTTP メソッドとステータスコード
Method Purpose Success Code Body
GET Read 200 OK Resource/collection
POST Create 201 Created Created resource + Location header
PUT Full replace 200 OK Updated resource
PATCH Partial update 200 OK Updated resource
DELETE Remove 204 No Content (empty)
Key error codes: 400 (bad input), 401 (unauthenticated), 403 (forbidden),
404 (not found), 409 (conflict), 422 (validation), 429 (rate limited)
ステップ 4: Express の実装
// src/app.js
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
const app = express();
app.use(helmet());
app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || '*' }));
app.use(express.json({ limit: '10kb' }));
app.use('/api/v1/users', usersRouter);
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.use(notFound);
app.use(errorHandler);
// src/routes/users.js — Zod によるバリデーション
import { Router } from 'express';
import { z } from 'zod';
const createUserSchema = z.object({
body: z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
password: z.string().min(8).max(128),
}),
});
router.get('/', authenticate, validate(listSchema), usersController.list);
router.post('/', validate(createUserSchema), usersController.create);
router.get('/:id', authenticate, usersController.getOne);
router.patch('/:id', authenticate, validate(updateSchema), usersController.update);
router.delete('/:id', authenticate, authorize('admin'), usersController.remove);
// src/controllers/users.js
export async function list(req, res) {
const { page, limit, sort, search } = req.query;
const [users, total] = await Promise.all([
db.user.findMany({ where: search ? { name: { contains: search } } : {}, skip: (page - 1) * limit, take: limit }),
db.user.count(),
]);
res.json({ data: users, meta: { page, limit, total, totalPages: Math.ceil(total / limit) } });
}
export async function create(req, res) {
const existing = await db.user.findUnique({ where: { email: req.body.email } });
if (existing) throw new AppError(409, 'Email already registered');
const user = await db.user.create({ data: { ...req.body, password: await hashPassword(req.body.password) } });
res.status(201).location(`/api/v1/users/${user.id}`).json({ data: user });
}
ステップ 5: ミドルウェア (Auth, Validation, Errors)
// Auth
export function authenticate(req, res, next) {
const header = req.headers.authorization;
if (!header?.startsWith('Bearer ')) throw new AppError(401, 'Missing token');
try { req.user = jwt.verify(header.slice(7), process.env.JWT_SECRET); next(); }
catch { throw new AppError(401, 'Invalid token'); }
}
// Validation
export function validate(schema) {
return (req, res, next) => {
const result = schema.safeParse({ body: req.body, query: req.query, params: req.params });
if (!result.success) throw new AppError(400, 'Validation failed', result.error.issues);
Object.assign(req, result.data);
next();
};
}
// Error handler
export function errorHandler(err, req, res, next) {
const status = err.statusCode || 500;
res.status(status).json({
error: { code: err.code || 'INTERNAL_ERROR', message: status === 500 ? 'Internal server error' : err.message },
});
}
ステップ 6: FastAPI の実装
from fastapi import FastAPI, APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, EmailStr, Field
app = FastAPI(title="My API", version="1.0.0", docs_url="/api/docs")
class UserCreate(BaseModel):
email: EmailStr
name: str = Field(min_length=2, max_length=100)
password: str = Field(min_length=8, max_length=128)
class UserResponse(BaseModel):
id: str; email: str; name: str; created_at: datetime
model_config = {"from_attributes": True}
router = APIRouter()
@router.get("", response_model=PaginatedResponse[UserResponse])
async def list_users(page: int = Query(1, ge=1), limit: int = Query(20, ge=1, le=100), db=Depends(get_db)):
users, total = await user_service.get_many(db, page=page, limit=limit)
return {"data": users, "meta": {"page": page, "limit": limit, "total": total}}
@router.post("", response_model=UserResponse, status_code=201)
async def create_user(body: UserCreate, db=Depends(get_db)):
existing = await user_service.get_by_email(db, body.email)
if existing: raise HTTPException(409, "Email already registered")
return await user_service.create(db, body)
app.include_router(router, prefix="/api/v1/users", tags=["users"])
ステップ 7: ページネーションとフィルタリング
オフセットベース: GET /api/v1/posts?page=2&limit=20 — `{ data, meta: { page, limit, total を返します。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
REST API
Overview
Design and build production-grade RESTful APIs following industry conventions. This skill covers resource modeling, HTTP semantics, authentication, validation, pagination, versioning, documentation, error handling, and security — with examples in Express (Node.js) and FastAPI (Python).
Instructions
Step 1: Project Setup
Express:
npm install express cors helmet morgan compression zod jsonwebtoken bcrypt swagger-jsdoc swagger-ui-express
FastAPI:
pip install "fastapi[standard]" uvicorn sqlalchemy pydantic-settings python-jose[cryptography] passlib[bcrypt]
Step 2: Resource Design
Resource Endpoint Methods
Users /api/v1/users GET, POST
User /api/v1/users/:id GET, PUT, PATCH, DELETE
User Posts /api/v1/users/:id/posts GET
Posts /api/v1/posts GET, POST
Post Comments /api/v1/posts/:id/comments GET, POST
Rules: plural nouns (/users), no verbs in URLs, max 2 nesting levels, kebab-case (/user-profiles).
Step 3: HTTP Methods and Status Codes
Method Purpose Success Code Body
GET Read 200 OK Resource/collection
POST Create 201 Created Created resource + Location header
PUT Full replace 200 OK Updated resource
PATCH Partial update 200 OK Updated resource
DELETE Remove 204 No Content (empty)
Key error codes: 400 (bad input), 401 (unauthenticated), 403 (forbidden),
404 (not found), 409 (conflict), 422 (validation), 429 (rate limited)
Step 4: Express Implementation
// src/app.js
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
const app = express();
app.use(helmet());
app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || '*' }));
app.use(express.json({ limit: '10kb' }));
app.use('/api/v1/users', usersRouter);
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.use(notFound);
app.use(errorHandler);
// src/routes/users.js — validation with Zod
import { Router } from 'express';
import { z } from 'zod';
const createUserSchema = z.object({
body: z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
password: z.string().min(8).max(128),
}),
});
router.get('/', authenticate, validate(listSchema), usersController.list);
router.post('/', validate(createUserSchema), usersController.create);
router.get('/:id', authenticate, usersController.getOne);
router.patch('/:id', authenticate, validate(updateSchema), usersController.update);
router.delete('/:id', authenticate, authorize('admin'), usersController.remove);
// src/controllers/users.js
export async function list(req, res) {
const { page, limit, sort, search } = req.query;
const [users, total] = await Promise.all([
db.user.findMany({ where: search ? { name: { contains: search } } : {}, skip: (page - 1) * limit, take: limit }),
db.user.count(),
]);
res.json({ data: users, meta: { page, limit, total, totalPages: Math.ceil(total / limit) } });
}
export async function create(req, res) {
const existing = await db.user.findUnique({ where: { email: req.body.email } });
if (existing) throw new AppError(409, 'Email already registered');
const user = await db.user.create({ data: { ...req.body, password: await hashPassword(req.body.password) } });
res.status(201).location(`/api/v1/users/${user.id}`).json({ data: user });
}
Step 5: Middleware (Auth, Validation, Errors)
// Auth
export function authenticate(req, res, next) {
const header = req.headers.authorization;
if (!header?.startsWith('Bearer ')) throw new AppError(401, 'Missing token');
try { req.user = jwt.verify(header.slice(7), process.env.JWT_SECRET); next(); }
catch { throw new AppError(401, 'Invalid token'); }
}
// Validation
export function validate(schema) {
return (req, res, next) => {
const result = schema.safeParse({ body: req.body, query: req.query, params: req.params });
if (!result.success) throw new AppError(400, 'Validation failed', result.error.issues);
Object.assign(req, result.data);
next();
};
}
// Error handler
export function errorHandler(err, req, res, next) {
const status = err.statusCode || 500;
res.status(status).json({
error: { code: err.code || 'INTERNAL_ERROR', message: status === 500 ? 'Internal server error' : err.message },
});
}
Step 6: FastAPI Implementation
from fastapi import FastAPI, APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, EmailStr, Field
app = FastAPI(title="My API", version="1.0.0", docs_url="/api/docs")
class UserCreate(BaseModel):
email: EmailStr
name: str = Field(min_length=2, max_length=100)
password: str = Field(min_length=8, max_length=128)
class UserResponse(BaseModel):
id: str; email: str; name: str; created_at: datetime
model_config = {"from_attributes": True}
router = APIRouter()
@router.get("", response_model=PaginatedResponse[UserResponse])
async def list_users(page: int = Query(1, ge=1), limit: int = Query(20, ge=1, le=100), db=Depends(get_db)):
users, total = await user_service.get_many(db, page=page, limit=limit)
return {"data": users, "meta": {"page": page, "limit": limit, "total": total}}
@router.post("", response_model=UserResponse, status_code=201)
async def create_user(body: UserCreate, db=Depends(get_db)):
existing = await user_service.get_by_email(db, body.email)
if existing: raise HTTPException(409, "Email already registered")
return await user_service.create(db, body)
app.include_router(router, prefix="/api/v1/users", tags=["users"])
Step 7: Pagination and Filtering
Offset-based: GET /api/v1/posts?page=2&limit=20 — returns { data, meta: { page, limit, total, totalPages } }
Cursor-based: GET /api/v1/posts?cursor=eyJpZCI6MTAwfQ&limit=20 — returns { data, meta: { nextCursor, hasMore } }
Common query params: sort=-createdAt,title, fields=id,title, search=keyword, status=active, createdAfter=2024-01-01.
Examples
Example 1: Build a CRUD API for a project management app
User prompt: "Create a REST API with Express for managing projects and tasks. Include JWT authentication, input validation, and paginated list endpoints."
The agent will:
- Set up Express with
helmet,cors,compression, and JSON body parsing - Define routes:
GET/POST /api/v1/projects,GET/PATCH/DELETE /api/v1/projects/:id,GET/POST /api/v1/projects/:id/tasks - Create Zod schemas for
createProjectandupdateProjectinput validation - Implement JWT authentication middleware that extracts the user from the Bearer token
- Add paginated list endpoints returning
{ data, meta: { page, limit, total, totalPages } } - Set up a global error handler returning
{ error: { code, message } }with proper HTTP status codes
Example 2: Add FastAPI endpoints with auto-generated docs
User prompt: "Create a FastAPI backend for a blog with users and posts. I want automatic OpenAPI documentation and Pydantic validation."
The agent will:
- Define Pydantic models:
UserCreate,UserResponse,PostCreate,PostResponse, andPaginatedResponse[T] - Create routers for
/api/v1/usersand/api/v1/postswith proper HTTP methods and status codes - Add dependency injection for database sessions and current user authentication
- FastAPI automatically generates interactive docs at
/api/docs(Swagger UI) and/api/redoc - Implement proper error handling with
HTTPExceptionusing correct status codes (409 for duplicate email, 404 for missing resources)
Guidelines
- Consistent response format — always wrap in
{ data: ... }or{ error: ... } - Validate all input — never trust request body, query, or params
- Use proper status codes — 201 for creation, 204 for delete, 409 for conflicts
- Include Location header — on 201 responses, point to the created resource
- Pagination by default — never return unbounded collections
- Rate limit everything — stricter limits on auth endpoints
- CORS configured explicitly — never use
*in production - Idempotent PUT/DELETE — calling twice produces the same result
- Error responses include machine-readable codes —
VALIDATION_FAILED, not just messages - Version from day one —
/api/v1/costs nothing and saves future pain