# API Design & Documentation

**Meta-Description:** REST API Design Best Practices. OpenAPI Specification, Dokumentation mit Swagger und Developer Experience optimieren.

**Keywords:** API Design, REST API, OpenAPI, Swagger, API Documentation, Developer Experience, API Best Practices

---

## Einführung

**Gutes API Design** ist entscheidend für Developer Experience. Mit **OpenAPI/Swagger** können APIs dokumentiert, getestet und generiert werden. Dieser Guide zeigt Best Practices für konsistente, intuitive APIs.

---

## API Design Overview

```
┌─────────────────────────────────────────────────────────────┐
│              REST API DESIGN PRINCIPLES                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  URL Structure:                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Resources (Nouns, plural):                         │   │
│  │  ├── GET    /users          List users             │   │
│  │  ├── POST   /users          Create user            │   │
│  │  ├── GET    /users/{id}     Get user               │   │
│  │  ├── PUT    /users/{id}     Update user            │   │
│  │  ├── PATCH  /users/{id}     Partial update         │   │
│  │  └── DELETE /users/{id}     Delete user            │   │
│  │                                                     │   │
│  │  Nested Resources:                                  │   │
│  │  ├── GET  /users/{id}/projects                     │   │
│  │  └── POST /users/{id}/projects                     │   │
│  │                                                     │   │
│  │  Query Parameters:                                  │   │
│  │  ├── ?page=1&limit=20        Pagination            │   │
│  │  ├── ?sort=createdAt:desc    Sorting               │   │
│  │  ├── ?filter[status]=active  Filtering             │   │
│  │  └── ?fields=id,name,email   Field selection       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  HTTP Status Codes:                                         │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  2xx Success:                                       │   │
│  │  ├── 200 OK                 Successful request     │   │
│  │  ├── 201 Created            Resource created       │   │
│  │  └── 204 No Content         Successful, no body    │   │
│  │                                                     │   │
│  │  4xx Client Errors:                                 │   │
│  │  ├── 400 Bad Request        Invalid input          │   │
│  │  ├── 401 Unauthorized       Not authenticated      │   │
│  │  ├── 403 Forbidden          Not authorized         │   │
│  │  ├── 404 Not Found          Resource not found     │   │
│  │  └── 422 Unprocessable      Validation failed      │   │
│  │                                                     │   │
│  │  5xx Server Errors:                                 │   │
│  │  ├── 500 Internal Error     Server error           │   │
│  │  └── 503 Service Unavailable Temporarily down      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

---

## OpenAPI Specification

```yaml
# openapi/api.yaml
openapi: 3.1.0
info:
  title: My SaaS API
  description: API for managing projects and tasks
  version: 1.0.0
  contact:
    name: API Support
    email: api@example.com
    url: https://example.com/support
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.example.com/v1
    description: Production
  - url: https://api.staging.example.com/v1
    description: Staging
  - url: http://localhost:3000/api/v1
    description: Local development

tags:
  - name: Projects
    description: Project management endpoints
  - name: Tasks
    description: Task management endpoints
  - name: Users
    description: User management endpoints

paths:
  /projects:
    get:
      tags: [Projects]
      summary: List all projects
      description: Returns a paginated list of projects for the authenticated user
      operationId: listProjects
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/PageParam'
        - $ref: '#/components/parameters/LimitParam'
        - name: status
          in: query
          description: Filter by status
          schema:
            type: string
            enum: [active, archived, draft]
        - name: sort
          in: query
          description: Sort field and direction
          schema:
            type: string
            example: createdAt:desc
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

    post:
      tags: [Projects]
      summary: Create a project
      description: Creates a new project
      operationId: createProject
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectInput'
      responses:
        '201':
          description: Project created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '400':
          $ref: '#/components/responses/BadRequest'
        '422':
          $ref: '#/components/responses/ValidationError'

  /projects/{projectId}:
    get:
      tags: [Projects]
      summary: Get a project
      operationId: getProject
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/ProjectIdParam'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '404':
          $ref: '#/components/responses/NotFound'

    patch:
      tags: [Projects]
      summary: Update a project
      operationId: updateProject
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/ProjectIdParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProjectInput'
      responses:
        '200':
          description: Project updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'

    delete:
      tags: [Projects]
      summary: Delete a project
      operationId: deleteProject
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/ProjectIdParam'
      responses:
        '204':
          description: Project deleted

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  parameters:
    ProjectIdParam:
      name: projectId
      in: path
      required: true
      description: Project ID
      schema:
        type: string
        format: uuid

    PageParam:
      name: page
      in: query
      description: Page number
      schema:
        type: integer
        minimum: 1
        default: 1

    LimitParam:
      name: limit
      in: query
      description: Items per page
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20

  schemas:
    Project:
      type: object
      required: [id, name, status, createdAt]
      properties:
        id:
          type: string
          format: uuid
          example: '123e4567-e89b-12d3-a456-426614174000'
        name:
          type: string
          minLength: 1
          maxLength: 100
          example: 'My Project'
        description:
          type: string
          maxLength: 1000
        status:
          type: string
          enum: [active, archived, draft]
          default: active
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    CreateProjectInput:
      type: object
      required: [name]
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        description:
          type: string
          maxLength: 1000

    UpdateProjectInput:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        description:
          type: string
          maxLength: 1000
        status:
          type: string
          enum: [active, archived, draft]

    ProjectListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Project'
        pagination:
          $ref: '#/components/schemas/Pagination'

    Pagination:
      type: object
      properties:
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        totalPages:
          type: integer

    Error:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
        details:
          type: object

  responses:
    BadRequest:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    ValidationError:
      description: Validation error
      content:
        application/json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Error'
              - type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        field:
                          type: string
                        message:
                          type: string

    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
```

---

## Type Generation from OpenAPI

```typescript
// scripts/generate-types.ts
import { generateApi } from 'swagger-typescript-api';
import path from 'path';

generateApi({
  name: 'api-client.ts',
  output: path.resolve(__dirname, '../lib/api'),
  input: path.resolve(__dirname, '../openapi/api.yaml'),
  httpClientType: 'fetch',
  generateClient: true,
  generateRouteTypes: true,
  generateResponses: true,
  extractRequestParams: true,
  extractRequestBody: true,
  unwrapResponseData: true,
  prettier: {
    printWidth: 100,
    singleQuote: true
  }
});
```

```typescript
// lib/api/client.ts - Generated API Client Usage
import { Api } from './api-client';

const api = new Api({
  baseUrl: process.env.NEXT_PUBLIC_API_URL,
  securityWorker: async () => {
    const token = await getAccessToken();
    return token ? { headers: { Authorization: `Bearer ${token}` } } : {};
  }
});

// Type-safe API calls
export async function getProjects(params?: {
  page?: number;
  limit?: number;
  status?: 'active' | 'archived' | 'draft';
}) {
  const response = await api.projects.listProjects(params);
  return response.data;
}

export async function createProject(input: {
  name: string;
  description?: string;
}) {
  const response = await api.projects.createProject(input);
  return response.data;
}
```

---

## API Response Format

```typescript
// lib/api/response.ts
import { NextResponse } from 'next/server';

interface ApiResponse<T> {
  data?: T;
  error?: {
    code: string;
    message: string;
    details?: unknown;
  };
  pagination?: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
  };
}

export function success<T>(
  data: T,
  status: number = 200
): NextResponse<ApiResponse<T>> {
  return NextResponse.json({ data }, { status });
}

export function paginated<T>(
  data: T[],
  pagination: { page: number; limit: number; total: number }
): NextResponse<ApiResponse<T[]>> {
  return NextResponse.json({
    data,
    pagination: {
      ...pagination,
      totalPages: Math.ceil(pagination.total / pagination.limit)
    }
  });
}

export function created<T>(data: T): NextResponse<ApiResponse<T>> {
  return success(data, 201);
}

export function noContent(): NextResponse {
  return new NextResponse(null, { status: 204 });
}

export function error(
  code: string,
  message: string,
  status: number = 400,
  details?: unknown
): NextResponse<ApiResponse<never>> {
  return NextResponse.json(
    { error: { code, message, details } },
    { status }
  );
}

export function badRequest(message: string, details?: unknown) {
  return error('BAD_REQUEST', message, 400, details);
}

export function unauthorized(message: string = 'Unauthorized') {
  return error('UNAUTHORIZED', message, 401);
}

export function forbidden(message: string = 'Forbidden') {
  return error('FORBIDDEN', message, 403);
}

export function notFound(resource: string = 'Resource') {
  return error('NOT_FOUND', `${resource} not found`, 404);
}

export function validationError(errors: Array<{ field: string; message: string }>) {
  return error('VALIDATION_ERROR', 'Validation failed', 422, { errors });
}

export function internalError(message: string = 'Internal server error') {
  return error('INTERNAL_ERROR', message, 500);
}
```

---

## Interactive Documentation

```tsx
// app/docs/api/page.tsx
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';

export default function ApiDocsPage() {
  return (
    <div className="min-h-screen">
      <SwaggerUI
        url="/openapi/api.yaml"
        docExpansion="list"
        defaultModelsExpandDepth={-1}
        displayRequestDuration={true}
        filter={true}
        showExtensions={true}
        tryItOutEnabled={true}
      />
    </div>
  );
}

// Alternative: Custom docs with syntax highlighting
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';

function CodeExample({ code, language }: { code: string; language: string }) {
  return (
    <SyntaxHighlighter
      language={language}
      style={vscDarkPlus}
      customStyle={{ borderRadius: '8px' }}
    >
      {code}
    </SyntaxHighlighter>
  );
}
```

---

## API Design Checklist

| Aspect | Best Practice |
|--------|--------------|
| **URLs** | Use nouns, plural, lowercase |
| **HTTP Methods** | Match CRUD operations |
| **Status Codes** | Use appropriate codes |
| **Errors** | Consistent format with codes |
| **Pagination** | Always paginate lists |
| **Versioning** | Use URL versioning (/v1/) |
| **Documentation** | OpenAPI specification |
| **Authentication** | Bearer tokens, API keys |

---

## Fazit

Gutes API Design erfordert:

1. **Konsistenz**: Einheitliche Struktur und Namenskonventionen
2. **OpenAPI**: Maschinenlesbare Spezifikation
3. **Dokumentation**: Interaktiv und aktuell
4. **Type Safety**: Generierte Typen aus Spec

Developer Experience beginnt mit gutem API Design.

---

## Bildprompts

1. "API documentation page with Swagger UI, interactive endpoints"
2. "REST API resource diagram, CRUD operations visualization"
3. "OpenAPI specification editor, YAML code with validation"

---

## Quellen

- [OpenAPI Specification](https://spec.openapis.org/oas/latest.html)
- [REST API Design Guide](https://restfulapi.net/)
- [Google API Design Guide](https://cloud.google.com/apis/design)
- [Microsoft REST API Guidelines](https://github.com/microsoft/api-guidelines)
