Skip to content
Back to skills

Api Design

ASecurity

Guidelines for designing RESTful APIs and TypeScript interfaces. Use when designing new endpoints, reviewing API contracts, or structuring data models.

  • 8 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 29, 2026
developmenttypescriptgoapisecurity

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned May 29, 2026

npx -y skills add zjunlp/Skills --skill api-design --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Api Design?

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

Security grade badge for Api Design
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/zjunlp-api-design/badge)](https://www.skillsdirectory.com/skills/zjunlp-api-design)

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

Download with Pro
SKILL.md
---
name: api-design
description: Guidelines for designing RESTful APIs and TypeScript interfaces. Use when designing new endpoints, reviewing API contracts, or structuring data models.
license: MIT
---

# 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

| Method | Purpose          | Idempotent | Body |
| ------ | ---------------- | ---------- | ---- |
| GET    | Read resource    | Yes        | No   |
| POST   | Create resource  | No         | Yes  |
| PUT    | Replace resource | Yes        | Yes  |
| PATCH  | Update resource  | No         | Yes  |
| DELETE | Remove resource  | Yes        | No   |

### 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

### URL Versioning (Recommended)

```
/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

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…