REST, GraphQL, and API design best practices. Use when designing APIs, defining contracts, or reviewing API architecture.
Provides REST, GraphQL, and API design best practices. Use when designing APIs, defining contracts, or reviewing API architecture.
/plugin marketplace add mjohnson518/claude_superpowers/plugin install mjohnson518-claude-superpowers@mjohnson518/claude_superpowersThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Design consistent, intuitive, and maintainable APIs following industry best practices.
https://api.example.com/v1/users/{userId}/orders/{orderId}
└─────┬─────┘ └┬┘ └──────────────┬────────────────┘
Base URL Version Resource Path
Conventions:
/users not /getUsers/users not /user/user-profiles not /userProfiles/users/{id}/orders| Method | Usage | Idempotent | Safe |
|---|---|---|---|
| GET | Retrieve resource(s) | Yes | Yes |
| POST | Create new resource | No | No |
| PUT | Replace entire resource | Yes | No |
| PATCH | Partial update | No | No |
| DELETE | Remove resource | Yes | No |
2xx Success
├── 200 OK - Successful GET/PUT/PATCH
├── 201 Created - Successful POST (with Location header)
├── 202 Accepted - Async operation started
└── 204 No Content - Successful DELETE
4xx Client Error
├── 400 Bad Request - Invalid request body/params
├── 401 Unauthorized - Missing/invalid authentication
├── 403 Forbidden - Authenticated but not authorized
├── 404 Not Found - Resource doesn't exist
├── 409 Conflict - Resource conflict (duplicate)
├── 422 Unprocessable - Validation failed
└── 429 Too Many Requests - Rate limited
5xx Server Error
├── 500 Internal Error - Unexpected server error
├── 502 Bad Gateway - Upstream service error
├── 503 Unavailable - Service temporarily down
└── 504 Gateway Timeout - Upstream timeout
// POST /api/v1/users
// Request
{
"email": "user@example.com",
"name": "John Doe",
"role": "user"
}
// Response (201 Created)
{
"id": "usr_abc123",
"email": "user@example.com",
"name": "John Doe",
"role": "user",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
// GET /api/v1/users?page=2&limit=20
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 150,
"totalPages": 8,
"hasNext": true,
"hasPrev": true
},
"links": {
"self": "/api/v1/users?page=2&limit=20",
"first": "/api/v1/users?page=1&limit=20",
"prev": "/api/v1/users?page=1&limit=20",
"next": "/api/v1/users?page=3&limit=20",
"last": "/api/v1/users?page=8&limit=20"
}
}
# Filtering
GET /api/v1/products?status=active&category=electronics
GET /api/v1/products?price[gte]=100&price[lte]=500
GET /api/v1/products?search=iphone
# Sorting
GET /api/v1/products?sort=price # Ascending
GET /api/v1/products?sort=-price # Descending
GET /api/v1/products?sort=-createdAt,name # Multiple
# Field selection
GET /api/v1/users?fields=id,email,name
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request data is invalid",
"details": [
{
"field": "email",
"message": "Must be a valid email address",
"code": "INVALID_FORMAT"
},
{
"field": "age",
"message": "Must be at least 18",
"code": "MIN_VALUE"
}
],
"requestId": "req_abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
}
type User {
id: ID!
email: String!
name: String!
profile: Profile
orders(first: Int, after: String): OrderConnection!
createdAt: DateTime!
}
type Profile {
bio: String
avatar: URL
location: String
}
type OrderConnection {
edges: [OrderEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type OrderEdge {
node: Order!
cursor: String!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type Query {
# Single resource
user(id: ID!): User
# List with filtering
users(
filter: UserFilter
orderBy: UserOrderBy
first: Int
after: String
): UserConnection!
# Search
searchUsers(query: String!, limit: Int = 10): [User!]!
}
input UserFilter {
status: UserStatus
role: UserRole
createdAfter: DateTime
}
enum UserOrderBy {
CREATED_AT_ASC
CREATED_AT_DESC
NAME_ASC
NAME_DESC
}
type Mutation {
# Create
createUser(input: CreateUserInput!): CreateUserPayload!
# Update
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
# Delete
deleteUser(id: ID!): DeleteUserPayload!
}
input CreateUserInput {
email: String!
name: String!
role: UserRole = USER
}
type CreateUserPayload {
user: User
errors: [UserError!]
}
type UserError {
field: String
message: String!
code: ErrorCode!
}
| Strategy | Example | Pros | Cons |
|---|---|---|---|
| URL Path | /v1/users | Clear, cacheable | Multiple codebases |
| Header | Accept: application/vnd.api.v1+json | Clean URLs | Harder to test |
| Query Param | /users?version=1 | Easy to test | Caching issues |
Recommendation: URL path versioning for simplicity.
# Response headers for deprecated endpoints
Deprecation: true
Sunset: Sat, 1 Jan 2025 00:00:00 GMT
Link: </v2/users>; rel="successor-version"
# Request
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# Response for expired token (401)
WWW-Authenticate: Bearer realm="api",
error="invalid_token",
error_description="Token has expired"
# Header approach (recommended)
X-API-Key: sk_live_abc123
# Query param (avoid - logs exposure)
GET /api/users?api_key=sk_live_abc123
Authorization: Bearer token
# Token includes scopes
{
"scope": "read:users write:orders",
"exp": 1705312200
}
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312200
Retry-After: 60
// 429 Too Many Requests
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 60 seconds.",
"retryAfter": 60
}
}
openapi: 3.0.3
info:
title: User API
version: 1.0.0
description: API for managing users
paths:
/users:
get:
summary: List users
tags: [Users]
parameters:
- name: page
in: query
schema:
type: integer
default: 1
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/UserList'
'401':
$ref: '#/components/responses/Unauthorized'
components:
schemas:
User:
type: object
required: [id, email, name]
properties:
id:
type: string
example: usr_abc123
email:
type: string
format: email
name:
type: string
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.