---
name: api-design
description: REST API design patterns including resource naming, status codes, pagination, filtering, error responses, versioning, rate limiting, and authentication for production APIs. Use when designing new endpoints, reviewing API contracts, or building public/partner-facing APIs.
---

# API Design Patterns

Conventions for 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
- Building public or partner-facing APIs

## Resource Design

### URL Structure

```
GET    /api/v1/users              # List
GET    /api/v1/users/:id          # Get one
POST   /api/v1/users              # Create
PUT    /api/v1/users/:id          # Replace
PATCH  /api/v1/users/:id          # Partial update
DELETE /api/v1/users/:id          # Remove

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

# Non-CRUD actions (verbs sparingly)
POST   /api/v1/orders/:id/cancel
```

### Naming Rules

- Resources: nouns, plural, lowercase, kebab-case
- Query params for filtering: `?status=active&sort=created_at`
- No verbs in URLs (use HTTP methods instead)
- No singular resource names

## Response Envelope

```json
{
  "success": true,
  "data": { ... },
  "error": null,
  "meta": {
    "total": 100,
    "page": 1,
    "limit": 20
  }
}
```

## Status Codes

| Code | Meaning | Use For |
|------|---------|---------|
| 200 | OK | GET, PUT, PATCH with body |
| 201 | Created | POST (include Location header) |
| 204 | No Content | DELETE |
| 400 | Bad Request | Validation failure |
| 401 | Unauthorized | Missing/invalid auth |
| 403 | Forbidden | Auth valid, insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate or state conflict |
| 422 | Unprocessable | Semantic validation failure |
| 429 | Too Many Requests | Rate limited |
| 500 | Internal Error | Server failure |

## Pagination

```
GET /api/v1/users?page=2&limit=20

Response meta:
{
  "total": 150,
  "page": 2,
  "limit": 20,
  "pages": 8
}
```

For large datasets, prefer cursor-based pagination:
```
GET /api/v1/events?cursor=abc123&limit=50
```

## Filtering and Sorting

```
GET /api/v1/orders?status=active&created_after=2024-01-01&sort=-created_at
```

- Use query params for filters
- Prefix with `-` for descending sort
- Support multiple sort fields: `sort=status,-created_at`

## Error Responses

```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "details": [
      {"field": "email", "message": "This field is required"}
    ]
  },
  "data": null
}
```

- Machine-readable error codes (UPPER_SNAKE_CASE)
- Human-readable messages
- Field-level details for validation errors
- Never expose stack traces or internal paths

## Authentication

- Use Bearer tokens in Authorization header
- API keys in X-API-Key header for service-to-service
- Never put secrets in URL query params
- Return 401 for missing auth, 403 for insufficient permissions

## Rate Limiting

Include headers in responses:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000
```

Stricter limits on: auth endpoints, write operations, expensive queries.

## Versioning

- URL path versioning: `/api/v1/`, `/api/v2/`
- Increment major version only for breaking changes
- Support previous version for minimum 6 months after deprecation
- Return `Sunset` header on deprecated endpoints
