Skip to content
Back to skills

2547 Api Antipatterns 60901c13

ASecurity

This document outlines common anti-patterns in REST API design that can lead to poor developer experience, maintenance nightmares, and scalability issues. Each anti-pattern is accompanied by examples and recommended solutions.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
businessgosqltestingdebuggingrefactoringapidatabasesecurityperformancedocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2547-api_antipatterns_60901c13 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2547 Api Antipatterns 60901c13?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2547 Api Antipatterns 60901c13
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2547-api-antipatterns-60901c13/badge)](https://www.skillsdirectory.com/skills/tools-only-2547-api-antipatterns-60901c13)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Common API Anti-Patterns and How to Avoid Them

## Introduction

This document outlines common anti-patterns in REST API design that can lead to poor developer experience, maintenance nightmares, and scalability issues. Each anti-pattern is accompanied by examples and recommended solutions.

## 1. Verb-Based URLs (The RPC Trap)

### Anti-Pattern
Using verbs in URLs instead of treating endpoints as resources.

```
❌ Bad Examples:
POST /api/getUsers
POST /api/createUser
GET  /api/deleteUser/123
POST /api/updateUserPassword
GET  /api/calculateOrderTotal/456
```

### Why It's Bad
- Violates REST principles
- Makes the API feel like RPC instead of REST
- HTTP methods lose their semantic meaning
- Reduces cacheability
- Harder to understand resource relationships

### Solution
```
✅ Good Examples:
GET    /api/users                    # Get users
POST   /api/users                    # Create user
DELETE /api/users/123               # Delete user
PATCH  /api/users/123/password      # Update password
GET    /api/orders/456/total        # Get order total
```

## 2. Inconsistent Naming Conventions

### Anti-Pattern
Mixed naming conventions across the API.

```json
❌ Bad Examples:
{
  "user_id": 123,           // snake_case
  "firstName": "John",      // camelCase
  "last-name": "Doe",       // kebab-case
  "EMAIL": "john@example.com", // UPPER_CASE
  "IsActive": true          // PascalCase
}
```

### Why It's Bad
- Confuses developers
- Increases cognitive load
- Makes code generation difficult
- Reduces API adoption

### Solution
```json
✅ Choose one convention and stick to it (camelCase recommended):
{
  "userId": 123,
  "firstName": "John",
  "lastName": "Doe",
  "email": "john@example.com",
  "isActive": true
}
```

## 3. Ignoring HTTP Status Codes

### Anti-Pattern
Always returning HTTP 200 regardless of the actual result.

```json
❌ Bad Example:
HTTP/1.1 200 OK
{
  "status": "error",
  "code": 404,
  "message": "User not found"
}
```

### Why It's Bad
- Breaks HTTP semantics
- Prevents proper error handling by clients
- Breaks caching and proxies
- Makes monitoring and debugging harder

### Solution
```json
✅ Good Example:
HTTP/1.1 404 Not Found
{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "User with ID 123 not found",
    "requestId": "req-abc123"
  }
}
```

## 4. Overly Complex Nested Resources

### Anti-Pattern
Creating deeply nested URL structures that are hard to navigate.

```
❌ Bad Example:
/companies/123/departments/456/teams/789/members/012/projects/345/tasks/678/comments/901
```

### Why It's Bad
- URLs become unwieldy
- Creates tight coupling between resources
- Makes independent resource access difficult
- Complicates authorization logic

### Solution
```
✅ Good Examples:
/tasks/678                    # Direct access to task
/tasks/678/comments          # Task comments
/users/012/tasks             # User's tasks
/projects/345?team=789       # Project filtering
```

## 5. Inconsistent Error Response Formats

### Anti-Pattern
Different error response structures across endpoints.

```json
❌ Bad Examples:
# Endpoint 1
{"error": "Invalid email"}

# Endpoint 2  
{"success": false, "msg": "User not found", "code": 404}

# Endpoint 3
{"errors": [{"field": "name", "message": "Required"}]}
```

### Why It's Bad
- Makes error handling complex for clients
- Reduces code reusability
- Poor developer experience

### Solution
```json
✅ Standardized Error Format:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request contains invalid data",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Email address is not valid"
      }
    ],
    "requestId": "req-123456",
    "timestamp": "2024-02-16T13:00:00Z"
  }
}
```

## 6. Missing or Poor Pagination

### Anti-Pattern
Returning all results in a single response or inconsistent pagination.

```json
❌ Bad Examples:
# No pagination (returns 10,000 records)
GET /api/users

# Inconsistent pagination parameters
GET /api/users?page=1&size=10
GET /api/orders?offset=0&limit=20
GET /api/products?start=0&count=50
```

### Why It's Bad
- Can cause performance issues
- May overwhelm clients
- Inconsistent pagination parameters confuse developers
- No way to estimate total results

### Solution
```json
✅ Good Example:
GET /api/users?page=1&pageSize=10

{
  "data": [...],
  "pagination": {
    "page": 1,
    "pageSize": 10,
    "total": 150,
    "totalPages": 15,
    "hasNext": true,
    "hasPrev": false
  }
}
```

## 7. Exposing Internal Implementation Details

### Anti-Pattern
URLs and field names that reflect database structure or internal architecture.

```
❌ Bad Examples:
/api/user_table/123
/api/db_orders
/api/legacy_customer_data
/api/temp_migration_users

Response fields:
{
  "user_id_pk": 123,
  "internal_ref_code": "usr_abc",
  "db_created_timestamp": 1645123456
}
```

### Why It's Bad
- Couples API to internal implementation
- Makes refactoring difficult
- Exposes unnecessary technical details
- Reduces API longevity

### Solution
```
✅ Good Examples:
/api/users/123
/api/orders
/api/customers

Response fields:
{
  "id": 123,
  "referenceCode": "usr_abc",
  "createdAt": "2024-02-16T13:00:00Z"
}
```

## 8. Overloading Single Endpoint

### Anti-Pattern
Using one endpoint for multiple unrelated operations based on request parameters.

```
❌ Bad Example:
POST /api/user-actions
{
  "action": "create_user",
  "userData": {...}
}

POST /api/user-actions  
{
  "action": "delete_user",
  "userId": 123
}

POST /api/user-actions
{
  "action": "send_email",
  "userId": 123,
  "emailType": "welcome"
}
```

### Why It's Bad
- Breaks REST principles
- Makes documentation complex
- Complicates client implementation
- Reduces discoverability

### Solution
```
✅ Good Examples:
POST   /api/users              # Create user
DELETE /api/users/123         # Delete user  
POST   /api/users/123/emails   # Send email to user
```

## 9. Lack of Versioning Strategy

### Anti-Pattern
Making breaking changes without version management.

```
❌ Bad Examples:
# Original API
{
  "name": "John Doe",
  "age": 30
}

# Later (breaking change with no versioning)
{
  "firstName": "John",
  "lastName": "Doe", 
  "birthDate": "1994-02-16"
}
```

### Why It's Bad
- Breaks existing clients
- Forces all clients to update simultaneously
- No graceful migration path
- Reduces API stability

### Solution
```
✅ Good Examples:
# Version 1
GET /api/v1/users/123
{
  "name": "John Doe",
  "age": 30
}

# Version 2 (with both versions supported)
GET /api/v2/users/123
{
  "firstName": "John",
  "lastName": "Doe",
  "birthDate": "1994-02-16",
  "age": 30  // Backwards compatibility
}
```

## 10. Poor Error Messages

### Anti-Pattern
Vague, unhelpful, or technical error messages.

```json
❌ Bad Examples:
{"error": "Something went wrong"}
{"error": "Invalid input"}
{"error": "SQL constraint violation: FK_user_profile_id"}
{"error": "NullPointerException at line 247"}
```

### Why It's Bad
- Doesn't help developers fix issues
- Increases support burden
- Poor developer experience
- May expose sensitive information

### Solution
```json
✅ Good Examples:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The email address is required and must be in a valid format",
    "details": [
      {
        "field": "email",
        "code": "REQUIRED",
        "message": "Email address is required"
      }
    ]
  }
}
```

## 11. Ignoring Content Negotiation

### Anti-Pattern
Hard-coding response format without considering client preferences.

```
❌ Bad Example:
# Always returns JSON regardless of Accept header
GET /api/users/123
Accept: application/xml
# Returns JSON anyway
```

### Why It's Bad
- Reduces API flexibility
- Ignores HTTP standards
- Makes integration harder for diverse clients

### Solution
```
✅ Good Example:
GET /api/users/123
Accept: application/xml

HTTP/1.1 200 OK
Content-Type: application/xml

<?xml version="1.0"?>
<user>
  <id>123</id>
  <name>John Doe</name>
</user>
```

## 12. Stateful API Design

### Anti-Pattern
Maintaining session state on the server between requests.

```
❌ Bad Example:
# Step 1: Initialize session
POST /api/session/init

# Step 2: Set context (requires step 1)
POST /api/session/set-user/123

# Step 3: Get data (requires steps 1 & 2)
GET /api/session/user-data
```

### Why It's Bad
- Breaks REST statelessness principle
- Reduces scalability
- Makes caching difficult
- Complicates error recovery

### Solution
```
✅ Good Example:
# Self-contained requests
GET /api/users/123/data
Authorization: Bearer jwt-token-with-context
```

## 13. Inconsistent HTTP Method Usage

### Anti-Pattern
Using HTTP methods inappropriately or inconsistently.

```
❌ Bad Examples:
GET  /api/users/123/delete    # DELETE operation with GET
POST /api/users/123/get       # GET operation with POST
PUT  /api/users               # Creating with PUT on collection
GET  /api/users/search        # Search with side effects
```

### Why It's Bad
- Violates HTTP semantics
- Breaks caching and idempotency expectations
- Confuses developers and tools

### Solution
```
✅ Good Examples:
DELETE /api/users/123         # Delete with DELETE
GET    /api/users/123         # Get with GET
POST   /api/users             # Create on collection
GET    /api/users?q=search    # Safe search with GET
```

## 14. Missing Rate Limiting Information

### Anti-Pattern
Not providing rate limiting information to clients.

```
❌ Bad Example:
HTTP/1.1 429 Too Many Requests
{
  "error": "Rate limit exceeded"
}
```

### Why It's Bad
- Clients don't know when to retry
- No information about current limits
- Difficult to implement proper backoff strategies

### Solution
```
✅ Good Example:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 3600

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "API rate limit exceeded",
    "retryAfter": 3600
  }
}
```

## 15. Chatty API Design

### Anti-Pattern
Requiring multiple API calls to accomplish common tasks.

```
❌ Bad Example:
# Get user profile requires 4 API calls
GET /api/users/123           # Basic info
GET /api/users/123/profile   # Profile details
GET /api/users/123/settings  # User settings
GET /api/users/123/stats     # User statistics
```

### Why It's Bad
- Increases latency
- Creates network overhead
- Makes mobile apps inefficient
- Complicates client implementation

### Solution
```
✅ Good Examples:
# Single call with expansion
GET /api/users/123?include=profile,settings,stats

# Or provide composite endpoints
GET /api/users/123/dashboard

# Or batch operations
POST /api/batch
{
  "requests": [
    {"method": "GET", "url": "/users/123"},
    {"method": "GET", "url": "/users/123/profile"}
  ]
}
```

## 16. No Input Validation

### Anti-Pattern
Accepting and processing invalid input without proper validation.

```json
❌ Bad Example:
POST /api/users
{
  "email": "not-an-email",
  "age": -5,
  "name": ""
}

# API processes this and fails later or stores invalid data
```

### Why It's Bad
- Leads to data corruption
- Security vulnerabilities
- Difficult to debug issues
- Poor user experience

### Solution
```json
✅ Good Example:
POST /api/users
{
  "email": "not-an-email",
  "age": -5,
  "name": ""
}

HTTP/1.1 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request contains invalid data",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Email must be a valid email address"
      },
      {
        "field": "age",
        "code": "INVALID_RANGE",
        "message": "Age must be between 0 and 150"
      },
      {
        "field": "name",
        "code": "REQUIRED",
        "message": "Name is required and cannot be empty"
      }
    ]
  }
}
```

## 17. Synchronous Long-Running Operations

### Anti-Pattern
Blocking the client with long-running operations in synchronous endpoints.

```
❌ Bad Example:
POST /api/reports/generate
# Client waits 30 seconds for response
```

### Why It's Bad
- Poor user experience
- Timeouts and connection issues
- Resource waste on client and server
- Doesn't scale well

### Solution
```
✅ Good Example:
# Async pattern
POST /api/reports
HTTP/1.1 202 Accepted
Location: /api/reports/job-123
{
  "jobId": "job-123",
  "status": "processing",
  "estimatedCompletion": "2024-02-16T13:05:00Z"
}

# Check status
GET /api/reports/job-123
{
  "jobId": "job-123",
  "status": "completed",
  "result": "/api/reports/download/report-456"
}
```

## Prevention Strategies

### 1. API Design Reviews
- Implement mandatory design reviews
- Use checklists based on these anti-patterns
- Include multiple stakeholders

### 2. API Style Guides
- Create and enforce API style guides
- Use linting tools for consistency
- Regular training for development teams

### 3. Automated Testing
- Test for common anti-patterns
- Include contract testing
- Monitor API usage patterns

### 4. Documentation Standards
- Require comprehensive API documentation
- Include examples and error scenarios
- Keep documentation up-to-date

### 5. Client Feedback
- Regularly collect feedback from API consumers
- Monitor API usage analytics
- Conduct developer experience surveys

## Conclusion

Avoiding these anti-patterns requires:
- Understanding REST principles
- Consistent design standards
- Regular review and refactoring
- Focus on developer experience
- Proper tooling and automation

Remember: A well-designed API is an asset that grows in value over time, while a poorly designed API becomes a liability that hampers development and adoption.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.