---
name: "engineer-api-design"
description: "Professional REST API design producing consistent, secure, and well-documented endpoints. Use whenever the user asks to design, create, review, or document an API — including 'diseñá una API', 'create an endpoint', 'API design', 'add a new route', 'design the backend', 'write an API for', 'REST endpoint', or any request involving serverless functions, API routes, endpoint structure, request/response schemas, pagination, or API documentation. Also triggers for Zod schema design, API error responses, rate limiting, or auth middleware. Do NOT use for frontend data fetching, GraphQL schema design, or database schema design (use database-design skill)."
---

# API Design — Professional REST Architecture

## Philosophy

A well-designed API is one that a developer can use correctly without reading extensive documentation. URLs should be guessable, responses should be predictable, errors should be actionable, and the entire interface should feel **boring** — in the best possible way.

This skill follows the conventions established by Microsoft's Azure API guidelines, Google's API design guide, and Postman's best practices: use nouns for resources, HTTP methods for actions, status codes for outcomes, and query parameters for modifiers.

The senior principle: **consistency over cleverness.** Every endpoint should look and behave like every other endpoint in the same API.

---

## API Design Workflow

### Step 1: Define Resources

Before writing any code, identify the domain resources:
- What are the nouns in the business domain? (events, clients, bookings, payments, leads)
- What are their relationships? (an event has many payments, a client has many events)
- Which resources are public vs. protected?

### Step 2: Map Operations to HTTP Methods

| Operation | Method | Endpoint | Status Code |
|-----------|--------|----------|-------------|
| List collection | GET | `/api/events` | 200 |
| Get single item | GET | `/api/events/:id` | 200 or 404 |
| Create item | POST | `/api/events` | 201 |
| Full update | PUT | `/api/events/:id` | 200 or 404 |
| Partial update | PATCH | `/api/events/:id` | 200 or 404 |
| Delete item | DELETE | `/api/events/:id` | 204 or 404 |
| Custom action | POST | `/api/events/:id/cancel` | 200 |

### Step 3: Design Request/Response Schemas

Read `references/schema-patterns.md` for Zod schema design, response envelopes, pagination, and error format.

Every endpoint needs:
- **Request schema:** Validated with Zod before processing
- **Response schema:** Consistent envelope with `data`, `error`, and `meta` fields
- **Error schema:** Standardized format across all endpoints

### Step 4: Add Cross-Cutting Concerns

Read `references/api-infrastructure.md` for auth, rate limiting, CORS, middleware, and logging patterns.

### Step 5: Document

Every endpoint should be self-documenting through its schema. For external APIs, generate OpenAPI/Swagger docs from the Zod schemas.

---

## URL Design Rules

### Use nouns, not verbs
```
✅ GET  /api/events         → List events
✅ POST /api/events         → Create event
❌ GET  /api/getEvents
❌ POST /api/createEvent
```

### Use plural nouns for collections
```
✅ /api/events
✅ /api/clients
❌ /api/event
❌ /api/client
```

### Use kebab-case for multi-word resources
```
✅ /api/booking-slots
✅ /api/market-intelligence
❌ /api/bookingSlots
❌ /api/MarketIntelligence
```

### Limit nesting to 1 level
```
✅ /api/events/:id/payments        → Payments for a specific event
✅ /api/clients/:id/events         → Events for a specific client
❌ /api/clients/:id/events/:id/payments/:id/installments
```

For deeper resources, promote them to top-level with a filter:
```
✅ /api/payments?eventId=123
```

### Use query parameters for filtering, sorting, pagination
```
✅ /api/events?status=confirmed&sort=-date&page=2&limit=20
❌ /api/events/confirmed/sorted-by-date/page/2
```

### Non-CRUD actions as sub-resources
```
✅ POST /api/events/:id/cancel      → Cancel an event
✅ POST /api/bookings/:id/confirm   → Confirm a booking
❌ POST /api/cancelEvent/:id
```

---

## HTTP Status Codes

Use consistently — don't invent meanings:

| Code | Meaning | When to use |
|------|---------|-------------|
| 200 | OK | Successful GET, PUT, PATCH, or action |
| 201 | Created | Successful POST that created a resource |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Validation error, malformed input |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate, stale data, or business rule conflict |
| 422 | Unprocessable | Valid JSON but semantically invalid |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Error | Unexpected server error |
| 502 | Bad Gateway | External service failure |
| 503 | Service Unavailable | Temporary overload or maintenance |

**Rule:** Never return 200 with an error in the body. Use the status code to communicate the outcome.

---

## Response Format

### Success response
```json
{
  "data": { "id": "evt-123", "title": "Birthday", "status": "confirmed" },
  "meta": { "requestId": "req-abc" }
}
```

### Collection response (with pagination)
```json
{
  "data": [
    { "id": "evt-123", "title": "Birthday" },
    { "id": "evt-456", "title": "Wedding" }
  ],
  "meta": {
    "page": 2,
    "limit": 20,
    "total": 87,
    "totalPages": 5
  }
}
```

### Error response
```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "fields": {
      "title": "Title is required",
      "date": "Date must be in the future"
    }
  },
  "meta": { "requestId": "req-def" }
}
```

**Consistency rule:** Every endpoint returns the same envelope shape. Consumers should never have to guess whether `data` or `error` will be present.

---

## Endpoint Implementation Pattern

For Vercel serverless functions or similar:

```typescript
export default async function handler(req: Request) {
  // 1. Method routing
  if (req.method !== 'POST') return methodNotAllowed(req.method);

  // 2. Authentication
  const user = await authenticate(req);
  if (!user) return unauthorized();

  // 3. Input validation
  const parsed = createEventSchema.safeParse(await req.json());
  if (!parsed.success) return validationError(parsed.error);

  // 4. Business logic
  try {
    const event = await eventService.create(parsed.data, user.id);
    return created(event);
  } catch (error) {
    return handleError(error);
  }
}
```

Each step has a single responsibility. Validation errors never reach business logic. Business logic never touches raw request objects.

---

## Idempotency

Operations that can be safely retried without side effects:
- **GET, PUT, DELETE** — inherently idempotent
- **POST** — NOT idempotent by default. Creating the same event twice creates two events.

For POST operations that should be idempotent (payments, bookings):
- Accept an `Idempotency-Key` header from the client
- Store the result keyed by this token
- On duplicate requests with the same key, return the stored result instead of processing again

---

## Reference Files

| File | When to read | Contents |
|------|-------------|----------|
| `references/schema-patterns.md` | Steps 3-4 | Zod schema design, response helpers, pagination, filtering, error formatting, TypeScript patterns |
| `references/api-infrastructure.md` | Step 4 | Authentication middleware, rate limiting, CORS, logging, request ID tracking, serverless patterns |

---

## Cross-Skill References

API design touches multiple concerns:
- **Database schema for the API?** → `database-design` skill for table design, RLS, migrations
- **Error responses?** → `error-handling` skill for custom error types, resilience patterns
- **Security (auth, rate limiting, input validation)?** → `security-hardening` skill
- **Testing the API?** → `testing-strategy` skill for integration test patterns
- **API performance?** → `performance-optimization` skill for caching, N+1 prevention
- **Logging API requests?** → `observability` skill for structured logging, correlation IDs
- **API in CI/CD?** → `ci-cd-pipeline` skill for automated testing and deploy
