Back to Mastra

API Design Guidelines

examples/unified-workspace/skills/api-design/SKILL.md

2025-12-184.7 KB
Original Source

API Design Guidelines

Overview

This skill provides guidelines for designing clean, consistent APIs. Apply these patterns when creating new endpoints, defining TypeScript interfaces, or reviewing API contracts.

Keywords: API design, REST, endpoints, TypeScript interfaces, data modeling, HTTP methods, response formats

REST Endpoint Design

URL Structure

/{resource}                    # Collection
/{resource}/{id}               # Single resource
/{resource}/{id}/{sub-resource} # Nested resource

Good examples:

  • GET /users - List users
  • GET /users/123 - Get user 123
  • POST /users/123/orders - Create order for user 123

Avoid:

  • /getUsers - Don't use verbs in URLs
  • /user/list - Don't use action words
  • /users/123/getOrders - HTTP method implies action

HTTP Methods

MethodPurposeIdempotentBody
GETRead resourceYesNo
POSTCreate resourceNoYes
PUTReplace resourceYesYes
PATCHUpdate resourceNoYes
DELETERemove resourceYesNo

Response Codes

Success:

  • 200 - OK (GET, PUT, PATCH with body)
  • 201 - Created (POST)
  • 204 - No Content (DELETE, PUT/PATCH without body)

Client errors:

  • 400 - Bad Request (validation failed)
  • 401 - Unauthorized (no/invalid auth)
  • 403 - Forbidden (no permission)
  • 404 - Not Found
  • 409 - Conflict (duplicate, state conflict)
  • 422 - Unprocessable Entity (semantic errors)

Server errors:

  • 500 - Internal Server Error
  • 503 - Service Unavailable

Response Formats

Success Response

typescript
// Single resource
{
  "data": {
    "id": "123",
    "name": "Example",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

// Collection
{
  "data": [...],
  "meta": {
    "total": 100,
    "page": 1,
    "pageSize": 20
  }
}

Error Response

typescript
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      }
    ]
  }
}

TypeScript Interface Design

Naming Conventions

typescript
// Entities use PascalCase nouns
interface User {}
interface OrderItem {}

// Request/Response types include suffix
interface CreateUserRequest {}
interface GetUserResponse {}

// Params types for function arguments
interface ListUsersParams {}

Required vs Optional

typescript
// Required fields: always present
interface User {
  id: string;
  email: string;
  createdAt: Date;
}

// Optional fields: may be undefined
interface CreateUserRequest {
  email: string;
  name?: string; // Optional
  metadata?: Record<string, unknown>;
}

Discriminated Unions

Use for type-safe variants:

typescript
type PaymentMethod =
  | { type: 'card'; cardNumber: string; expiry: string }
  | { type: 'bank'; accountNumber: string; routingNumber: string }
  | { type: 'crypto'; walletAddress: string };

// Usage
function processPayment(method: PaymentMethod) {
  switch (method.type) {
    case 'card':
      // TypeScript knows cardNumber exists
      return chargeCard(method.cardNumber);
    case 'bank':
      return initiateTransfer(method.accountNumber);
    case 'crypto':
      return sendCrypto(method.walletAddress);
  }
}

Pagination

Offset-based (Simple)

typescript
interface PaginationParams {
  page?: number; // Default: 1
  pageSize?: number; // Default: 20, max: 100
}

interface PaginatedResponse<T> {
  data: T[];
  meta: {
    page: number;
    pageSize: number;
    total: number;
    totalPages: number;
  };
}

Cursor-based (Scalable)

typescript
interface CursorParams {
  cursor?: string;
  limit?: number;
}

interface CursorResponse<T> {
  data: T[];
  meta: {
    nextCursor: string | null;
    hasMore: boolean;
  };
}

Versioning

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

Header Versioning

Accept: application/vnd.api+json; version=2

Common Patterns

Filtering

GET /users?status=active&role=admin
GET /orders?createdAfter=2024-01-01&createdBefore=2024-02-01

Sorting

GET /users?sort=createdAt:desc
GET /users?sort=lastName:asc,firstName:asc

Field Selection

GET /users?fields=id,name,email
GET /users/123?include=orders,profile

Security Considerations

  1. Authentication - Use Bearer tokens in Authorization header
  2. Rate limiting - Include X-RateLimit-* headers
  3. Input validation - Validate all request bodies with schemas
  4. Output encoding - Escape HTML in responses if rendered
  5. CORS - Configure allowed origins explicitly