# How to Create API Design Patterns for ECC: A Complete Guide to RESTful Architecture

> Learn to create API design patterns for ECC with this guide. Explore RESTful architecture, resource naming, response envelopes, pagination, and authentication for production-ready APIs.

- Repository: [Affaan Mustafa/ECC](https://github.com/affaan-m/ECC)
- Tags: how-to-guide
- Published: 2026-05-26

---

**The ECC repository provides a comprehensive, language-agnostic API design skill located in [`skills/api-design/SKILL.md`](https://github.com/affaan-m/ECC/blob/main/skills/api-design/SKILL.md) that defines eight core patterns for building production-ready REST APIs, including resource-first URL naming, standard response envelopes, pagination strategies, and authentication schemes.**

The **api-design** skill in the ECC (Enterprise Coding Copilot) repository offers a reusable framework for creating consistent, secure, and evolvable APIs across any technology stack. According to the `affaan-m/ECC` source code, these patterns standardize everything from URL structure to error handling, ensuring that services built within the ECC ecosystem maintain uniformity and high quality.

## Core Principles of the ECC API Design Pattern

The foundation of the ECC API design patterns rests on resource-oriented architecture and strict conventions for HTTP semantics. These rules ensure that APIs are predictable, cacheable, and easy to consume.

### Resource-First URL Design

In [`skills/api-design/SKILL.md`](https://github.com/affaan-m/ECC/blob/main/skills/api-design/SKILL.md) (lines 22-40), URLs are mandated to be **nouns**, plural, lowercase, and kebab-case. The resource-first approach means endpoints represent entities rather than actions.

- **Base URLs**: Use `/api/v1/users` instead of `/getUsers`
- **Sub-resources**: Nest related resources, e.g., `/api/v1/users/{id}/orders`
- **Actions**: Reserve actions for true controllers, e.g., `/api/v1/users/{id}/activate`

This convention eliminates ambiguity and aligns with RESTful principles where HTTP methods define the action performed on the resource.

### HTTP Method Semantics and Status Codes

Lines 58-89 of the skill specification map HTTP verbs to their idempotency and safety characteristics. Each method has prescribed status codes for success, client error, and server error scenarios.

**Method mappings**:
- **GET**: Safe and idempotent; returns `200 OK` or `404 Not Found`
- **POST**: Creates resources; returns `201 Created` with a `Location` header or `422 Unprocessable Entity` for validation errors
- **PUT/PATCH**: Updates; returns `200 OK` or `204 No Content`
- **DELETE**: Removes resources; returns `204 No Content` or `404 Not Found`

### Standard Response Envelopes

Lines 114-172 define mandatory response envelopes that standardize client parsing. Success responses wrap data in a `data` field, while errors use a structured `error` object containing `code`, `message`, and optional `details`.

Success example:

```json
{
  "data": {
    "id": "usr_123",
    "email": "user@example.com"
  }
}

```

Error example:

```json
{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed",
    "details": ["email must be valid"]
  }
}

```

This envelope pattern ensures that clients can handle responses uniformly without inspecting HTTP status codes alone.

## Advanced Patterns for Scalable APIs

Beyond the basics, ECC provides patterns for handling large datasets, complex queries, and security concerns.

### Pagination Strategies

According to lines 198-246 of [`SKILL.md`](https://github.com/affaan-m/ECC/blob/main/SKILL.md), ECC supports two pagination models:

**Offset-based pagination** (simple, page-number):
- Use for datasets under 10,000 records
- Query parameters: `?page=2&limit=25`
- Response includes `total`, `page`, `size`, and `pages`

**Cursor-based pagination** (scalable):
- Use for large or rapidly changing datasets
- Query parameters: `?cursor=eyJpZCI6MTIzfQ==&limit=25`
- Response includes `next_cursor` and `has_more`

### Query String Conventions for Filtering and Sorting

Lines 248-286 define operators for advanced querying:

- **Equality**: `?status=active`
- **Range operators**: `?created_at[gte]=2023-01-01&created_at[lte]=2023-12-31`
- **Multi-value lists**: `?status=active,pending`
- **Nested fields**: `?profile.name=John` (dot notation)
- **Search**: `?q=search term` (full-text)

### Authentication, Authorization, and Rate Limiting

Lines 294-324 specify token-based authentication using `Authorization: Bearer <token>` or `X-API-Key` headers. Resource-level and role-based middleware examples validate permissions before handling requests.

Lines 326-354 describe tiered rate limiting with header-based limits:
- **Headers**: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`
- **Tiers**: Anonymous (low), Authenticated (medium), Premium (high), Internal (unlimited)
- **Error**: Returns `429 Too Many Requests` when exceeded

### API Versioning and Deprecation

Lines 356-384 mandate path-versioning (`/api/v1/...`) as the default strategy, with optional header-based versioning (`API-Version: 2023-11`). Deprecation workflows include `Sunset` headers and migration guides in the `Deprecation` header.

## Implementation Examples

The ECC repository provides reference implementations demonstrating these patterns in TypeScript, Python, and Go.

### TypeScript with Next.js

This example from [`skills/api-design/SKILL.md`](https://github.com/affaan-m/ECC/blob/main/skills/api-design/SKILL.md) (lines 401-440) shows Zod validation, proper status codes, and the `Location` header:

```typescript
import { z } from "zod";
import { NextRequest, NextResponse } from "next/server";

const createUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
});

export async function POST(req: NextRequest) {
  const body = await req.json();
  const parsed = createUserSchema.safeParse(body);

  if (!parsed.success) {
    return NextResponse.json(
      { error: { code: "validation_error", message: "Request validation failed", details: parsed.error.issues } },
      { status: 422 }
    );
  }

  const user = await createUser(parsed.data);
  return NextResponse.json(
    { data: user },
    { status: 201, headers: { Location: `/api/v1/users/${user.id}` } }
  );
}

```

### Python with Django REST Framework

Lines 442-476 demonstrate separate serializers for creation versus read operations, automatic headers, and error envelope handling:

```python
from rest_framework import serializers, viewsets, status
from rest_framework.response import Response

class CreateUserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    name = serializers.CharField(max_length=100)

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "email", "name", "created_at"]

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]

    def create(self, request):
        serializer = CreateUserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = UserService.create(**serializer.validated_data)
        return Response(
            {"data": UserSerializer(user).data},
            status=status.HTTP_201_CREATED,
            headers={"Location": f"/api/v1/users/{user.id}"},
        )

```

### Go with net/http

Lines 778-805 illustrate manual request decoding, validation, and response writing following ECC conventions:

```go
func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) {
    var req CreateUserRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        writeError(w, http.StatusBadRequest, "invalid_json", "Invalid request body")
        return
    }

    if err := req.Validate(); err != nil {
        writeError(w, http.StatusUnprocessableEntity, "validation_error", err.Error())
        return
    }

    user, err := h.service.Create(r.Context(), req)
    if err != nil {
        // handle conflict, internal errors, etc.
        writeError(w, http.StatusInternalServerError, "internal_error", "Internal error")
        return
    }

    w.Header().Set("Location", fmt.Sprintf("/api/v1/users/%s", user.ID))
    writeJSON(w, http.StatusCreated, map[string]any{"data": user})
}

```

## Summary

The ECC API design patterns provide a complete blueprint for RESTful architecture:

- **Resource-first URLs** use plural, kebab-case nouns to represent entities, avoiding action verbs in paths
- **Standard response envelopes** wrap success data in `data` keys and errors in structured `error` objects with codes and messages
- **HTTP semantics** enforce idempotency rules and appropriate status codes (`201` for creation, `422` for validation, `429` for rate limits)
- **Pagination** supports both offset-based (for small datasets) and cursor-based (for large scale) strategies
- **Security layers** include Bearer token authentication, tiered rate limiting, and role-based access control
- **Versioning** uses path-based strategy (`/api/v1/`) with formal deprecation workflows

## Frequently Asked Questions

### What file contains the complete API design specification for ECC?

The complete specification resides in [`skills/api-design/SKILL.md`](https://github.com/affaan-m/ECC/blob/main/skills/api-design/SKILL.md) in the `affaan-m/ECC` repository. This file contains line-by-line guidance on URL naming conventions, response envelopes, pagination, authentication, rate limiting, and versioning strategies applicable to any programming language.

### How should I format error responses in ECC API design patterns?

Error responses must follow the standard envelope defined in lines 114-172 of the skill file. Wrap errors in an `error` object containing `code` (machine-readable string), `message` (human-readable description), and optional `details` (array of specific validation issues). Return appropriate HTTP status codes such as `422` for validation errors or `429` for rate limiting.

### When should I use cursor-based pagination versus offset-based pagination?

Use **offset-based pagination** (page numbers) for datasets under 10,000 records where simplicity matters, as described in lines 198-220. Use **cursor-based pagination** for large datasets or rapidly changing data to prevent duplicate or skipped records during high-velocity writes, detailed in lines 221-246.

### Does ECC API design require specific authentication mechanisms?

The patterns support token-based authentication via `Authorization: Bearer <token>` or `X-API-Key` headers, specified in lines 294-324. While the pattern is agnostic to the specific token format (JWT, opaque), it mandates that authentication middleware enforce resource-level and role-based checks before processing requests.