api-design — ai-agents api-design, everything-claude-code, official, ai-agents, ide skills, anthropic, claude-code, developer-tools, Claude Code, Cursor, Windsurf

Verified
v1.0.0
GitHub

About this Skill

Ideal for API-focused Agents requiring mastery of REST API design patterns, including resource naming, status codes, and pagination. REST API design patterns including resource naming, status codes, pagination, filtering, error responses, versioning, and rate limiting for production APIs.

# Core Topics

affaan-m affaan-m
[55.0k]
[6781]
Updated: 3/1/2026

Agent Capability Analysis

The api-design skill by affaan-m is an open-source official AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance. Optimized for ai-agents, anthropic, claude-code.

Ideal Agent Persona

Ideal for API-focused Agents requiring mastery of REST API design patterns, including resource naming, status codes, and pagination.

Core Value

Empowers agents to craft consistent, developer-friendly REST APIs using conventions like kebab-case resource naming, versioning, and rate limiting, ensuring seamless integration with production environments via HTTP protocols and JSON data formats.

Capabilities Granted for api-design

Designing scalable API endpoints
Implementing robust error handling and response codes
Optimizing API performance with pagination and filtering

! Prerequisites & Limits

  • Assumes knowledge of HTTP and REST principles
  • Focused on REST API design, not other API styles like GraphQL
Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

api-design

Install api-design, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly

API Design Patterns

Conventions and best practices for designing consistent, developer-friendly REST APIs.

When to Activate

  • Designing new API endpoints
  • Reviewing existing API contracts
  • Adding pagination, filtering, or sorting
  • Implementing error handling for APIs
  • Planning API versioning strategy
  • Building public or partner-facing APIs

Resource Design

URL Structure

# Resources are nouns, plural, lowercase, kebab-case
GET    /api/v1/users
GET    /api/v1/users/:id
POST   /api/v1/users
PUT    /api/v1/users/:id
PATCH  /api/v1/users/:id
DELETE /api/v1/users/:id

# Sub-resources for relationships
GET    /api/v1/users/:id/orders
POST   /api/v1/users/:id/orders

# Actions that don't map to CRUD (use verbs sparingly)
POST   /api/v1/orders/:id/cancel
POST   /api/v1/auth/login
POST   /api/v1/auth/refresh

Naming Rules

# GOOD
/api/v1/team-members          # kebab-case for multi-word resources
/api/v1/orders?status=active  # query params for filtering
/api/v1/users/123/orders      # nested resources for ownership

# BAD
/api/v1/getUsers              # verb in URL
/api/v1/user                  # singular (use plural)
/api/v1/team_members          # snake_case in URLs
/api/v1/users/123/getOrders   # verb in nested resource

HTTP Methods and Status Codes

Method Semantics

MethodIdempotentSafeUse For
GETYesYesRetrieve resources
POSTNoNoCreate resources, trigger actions
PUTYesNoFull replacement of a resource
PATCHNo*NoPartial update of a resource
DELETEYesNoRemove a resource

*PATCH can be made idempotent with proper implementation

Status Code Reference

# Success
200 OK                    — GET, PUT, PATCH (with response body)
201 Created               — POST (include Location header)
204 No Content            — DELETE, PUT (no response body)

# Client Errors
400 Bad Request           — Validation failure, malformed JSON
401 Unauthorized          — Missing or invalid authentication
403 Forbidden             — Authenticated but not authorized
404 Not Found             — Resource doesn't exist
409 Conflict              — Duplicate entry, state conflict
422 Unprocessable Entity  — Semantically invalid (valid JSON, bad data)
429 Too Many Requests     — Rate limit exceeded

# Server Errors
500 Internal Server Error — Unexpected failure (never expose details)
502 Bad Gateway           — Upstream service failed
503 Service Unavailable   — Temporary overload, include Retry-After

Common Mistakes

# BAD: 200 for everything
{ "status": 200, "success": false, "error": "Not found" }

# GOOD: Use HTTP status codes semantically
HTTP/1.1 404 Not Found
{ "error": { "code": "not_found", "message": "User not found" } }

# BAD: 500 for validation errors
# GOOD: 400 or 422 with field-level details

# BAD: 200 for created resources
# GOOD: 201 with Location header
HTTP/1.1 201 Created
Location: /api/v1/users/abc-123

Response Format

Success Response

json
1{ 2 "data": { 3 "id": "abc-123", 4 "email": "alice@example.com", 5 "name": "Alice", 6 "created_at": "2025-01-15T10:30:00Z" 7 } 8}

Collection Response (with Pagination)

json
1{ 2 "data": [ 3 { "id": "abc-123", "name": "Alice" }, 4 { "id": "def-456", "name": "Bob" } 5 ], 6 "meta": { 7 "total": 142, 8 "page": 1, 9 "per_page": 20, 10 "total_pages": 8 11 }, 12 "links": { 13 "self": "/api/v1/users?page=1&per_page=20", 14 "next": "/api/v1/users?page=2&per_page=20", 15 "last": "/api/v1/users?page=8&per_page=20" 16 } 17}

Error Response

json
1{ 2 "error": { 3 "code": "validation_error", 4 "message": "Request validation failed", 5 "details": [ 6 { 7 "field": "email", 8 "message": "Must be a valid email address", 9 "code": "invalid_format" 10 }, 11 { 12 "field": "age", 13 "message": "Must be between 0 and 150", 14 "code": "out_of_range" 15 } 16 ] 17 } 18}

Response Envelope Variants

typescript
1// Option A: Envelope with data wrapper (recommended for public APIs) 2interface ApiResponse<T> { 3 data: T; 4 meta?: PaginationMeta; 5 links?: PaginationLinks; 6} 7 8interface ApiError { 9 error: { 10 code: string; 11 message: string; 12 details?: FieldError[]; 13 }; 14} 15 16// Option B: Flat response (simpler, common for internal APIs) 17// Success: just return the resource directly 18// Error: return error object 19// Distinguish by HTTP status code

Pagination

Offset-Based (Simple)

GET /api/v1/users?page=2&per_page=20

# Implementation
SELECT * FROM users
ORDER BY created_at DESC
LIMIT 20 OFFSET 20;

Pros: Easy to implement, supports "jump to page N" Cons: Slow on large offsets (OFFSET 100000), inconsistent with concurrent inserts

Cursor-Based (Scalable)

GET /api/v1/users?cursor=eyJpZCI6MTIzfQ&limit=20

# Implementation
SELECT * FROM users
WHERE id > :cursor_id
ORDER BY id ASC
LIMIT 21;  -- fetch one extra to determine has_next
json
1{ 2 "data": [...], 3 "meta": { 4 "has_next": true, 5 "next_cursor": "eyJpZCI6MTQzfQ" 6 } 7}

Pros: Consistent performance regardless of position, stable with concurrent inserts Cons: Cannot jump to arbitrary page, cursor is opaque

When to Use Which

Use CasePagination Type
Admin dashboards, small datasets (<10K)Offset
Infinite scroll, feeds, large datasetsCursor
Public APIsCursor (default) with offset (optional)
Search resultsOffset (users expect page numbers)

Filtering

# Simple equality
GET /api/v1/orders?status=active&customer_id=abc-123

# Comparison operators (use bracket notation)
GET /api/v1/products?price[gte]=10&price[lte]=100
GET /api/v1/orders?created_at[after]=2025-01-01

# Multiple values (comma-separated)
GET /api/v1/products?category=electronics,clothing

# Nested fields (dot notation)
GET /api/v1/orders?customer.country=US

Sorting

# Single field (prefix - for descending)
GET /api/v1/products?sort=-created_at

# Multiple fields (comma-separated)
GET /api/v1/products?sort=-featured,price,-created_at
# Search query parameter
GET /api/v1/products?q=wireless+headphones

# Field-specific search
GET /api/v1/users?email=alice

Sparse Fieldsets

# Return only specified fields (reduces payload)
GET /api/v1/users?fields=id,name,email
GET /api/v1/orders?fields=id,total,status&include=customer.name

Authentication and Authorization

Token-Based Auth

# Bearer token in Authorization header
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

# API key (for server-to-server)
GET /api/v1/data
X-API-Key: sk_live_abc123

Authorization Patterns

typescript
1// Resource-level: check ownership 2app.get("/api/v1/orders/:id", async (req, res) => { 3 const order = await Order.findById(req.params.id); 4 if (!order) return res.status(404).json({ error: { code: "not_found" } }); 5 if (order.userId !== req.user.id) return res.status(403).json({ error: { code: "forbidden" } }); 6 return res.json({ data: order }); 7}); 8 9// Role-based: check permissions 10app.delete("/api/v1/users/:id", requireRole("admin"), async (req, res) => { 11 await User.delete(req.params.id); 12 return res.status(204).send(); 13});

Rate Limiting

Headers

HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000

# When exceeded
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Try again in 60 seconds."
  }
}

Rate Limit Tiers

TierLimitWindowUse Case
Anonymous30/minPer IPPublic endpoints
Authenticated100/minPer userStandard API access
Premium1000/minPer API keyPaid API plans
Internal10000/minPer serviceService-to-service

Versioning

/api/v1/users
/api/v2/users

Pros: Explicit, easy to route, cacheable Cons: URL changes between versions

Header Versioning

GET /api/users
Accept: application/vnd.myapp.v2+json

Pros: Clean URLs Cons: Harder to test, easy to forget

Versioning Strategy

1. Start with /api/v1/ — don't version until you need to
2. Maintain at most 2 active versions (current + previous)
3. Deprecation timeline:
   - Announce deprecation (6 months notice for public APIs)
   - Add Sunset header: Sunset: Sat, 01 Jan 2026 00:00:00 GMT
   - Return 410 Gone after sunset date
4. Non-breaking changes don't need a new version:
   - Adding new fields to responses
   - Adding new optional query parameters
   - Adding new endpoints
5. Breaking changes require a new version:
   - Removing or renaming fields
   - Changing field types
   - Changing URL structure
   - Changing authentication method

Implementation Patterns

TypeScript (Next.js API Route)

typescript
1import { z } from "zod"; 2import { NextRequest, NextResponse } from "next/server"; 3 4const createUserSchema = z.object({ 5 email: z.string().email(), 6 name: z.string().min(1).max(100), 7}); 8 9export async function POST(req: NextRequest) { 10 const body = await req.json(); 11 const parsed = createUserSchema.safeParse(body); 12 13 if (!parsed.success) { 14 return NextResponse.json({ 15 error: { 16 code: "validation_error", 17 message: "Request validation failed", 18 details: parsed.error.issues.map(i => ({ 19 field: i.path.join("."), 20 message: i.message, 21 code: i.code, 22 })), 23 }, 24 }, { status: 422 }); 25 } 26 27 const user = await createUser(parsed.data); 28 29 return NextResponse.json( 30 { data: user }, 31 { 32 status: 201, 33 headers: { Location: `/api/v1/users/${user.id}` }, 34 }, 35 ); 36}

Python (Django REST Framework)

python
1from rest_framework import serializers, viewsets, status 2from rest_framework.response import Response 3 4class CreateUserSerializer(serializers.Serializer): 5 email = serializers.EmailField() 6 name = serializers.CharField(max_length=100) 7 8class UserSerializer(serializers.ModelSerializer): 9 class Meta: 10 model = User 11 fields = ["id", "email", "name", "created_at"] 12 13class UserViewSet(viewsets.ModelViewSet): 14 serializer_class = UserSerializer 15 permission_classes = [IsAuthenticated] 16 17 def get_serializer_class(self): 18 if self.action == "create": 19 return CreateUserSerializer 20 return UserSerializer 21 22 def create(self, request): 23 serializer = CreateUserSerializer(data=request.data) 24 serializer.is_valid(raise_exception=True) 25 user = UserService.create(**serializer.validated_data) 26 return Response( 27 {"data": UserSerializer(user).data}, 28 status=status.HTTP_201_CREATED, 29 headers={"Location": f"/api/v1/users/{user.id}"}, 30 )

Go (net/http)

go
1func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) { 2 var req CreateUserRequest 3 if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 4 writeError(w, http.StatusBadRequest, "invalid_json", "Invalid request body") 5 return 6 } 7 8 if err := req.Validate(); err != nil { 9 writeError(w, http.StatusUnprocessableEntity, "validation_error", err.Error()) 10 return 11 } 12 13 user, err := h.service.Create(r.Context(), req) 14 if err != nil { 15 switch { 16 case errors.Is(err, domain.ErrEmailTaken): 17 writeError(w, http.StatusConflict, "email_taken", "Email already registered") 18 default: 19 writeError(w, http.StatusInternalServerError, "internal_error", "Internal error") 20 } 21 return 22 } 23 24 w.Header().Set("Location", fmt.Sprintf("/api/v1/users/%s", user.ID)) 25 writeJSON(w, http.StatusCreated, map[string]any{"data": user}) 26}

API Design Checklist

Before shipping a new endpoint:

  • Resource URL follows naming conventions (plural, kebab-case, no verbs)
  • Correct HTTP method used (GET for reads, POST for creates, etc.)
  • Appropriate status codes returned (not 200 for everything)
  • Input validated with schema (Zod, Pydantic, Bean Validation)
  • Error responses follow standard format with codes and messages
  • Pagination implemented for list endpoints (cursor or offset)
  • Authentication required (or explicitly marked as public)
  • Authorization checked (user can only access their own resources)
  • Rate limiting configured
  • Response does not leak internal details (stack traces, SQL errors)
  • Consistent naming with existing endpoints (camelCase vs snake_case)
  • Documented (OpenAPI/Swagger spec updated)

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is api-design?

Ideal for API-focused Agents requiring mastery of REST API design patterns, including resource naming, status codes, and pagination. REST API design patterns including resource naming, status codes, pagination, filtering, error responses, versioning, and rate limiting for production APIs.

How do I install api-design?

Run the command: npx killer-skills add affaan-m/everything-claude-code/api-design. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for api-design?

Key use cases include: Designing scalable API endpoints, Implementing robust error handling and response codes, Optimizing API performance with pagination and filtering.

Which IDEs are compatible with api-design?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for api-design?

Assumes knowledge of HTTP and REST principles. Focused on REST API design, not other API styles like GraphQL.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add affaan-m/everything-claude-code/api-design. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use api-design immediately in the current project.

Related Skills

Looking for an alternative to api-design or another official skill for your workflow? Explore these related open-source skills.

View All

flags

Logo of facebook
facebook

Use when you need to check feature flag states, compare channels, or debug why a feature behaves differently across release channels.

243.6k
0
Developer

extract-errors

Logo of facebook
facebook

Use when adding new error messages to React, or seeing unknown error code warnings.

243.6k
0
Developer

fix

Logo of facebook
facebook

Use when you have lint errors, formatting issues, or before committing code to ensure it passes CI.

243.6k
0
Developer

flow

Logo of facebook
facebook

Use when you need to run Flow type checking, or when seeing Flow type errors in React code.

243.6k
0
Developer