Part 2: RESTful Design Principles and Best Practices

The Day My API Design Mattered

Two years into building microservices, our product team added 3 new developers. On their first day, they asked: "Where's the API documentation?" I opened Postman and showed them my endpoints:

POST /createUser
GET /getUserData?id=123
POST /update-product
DELETE /removeOrder
GET /api/v1/products/list
POST /products/create

They stared in confusion. "Which endpoints use /api/? Why mix camelCase and kebab-case? Is there a pattern?"

There wasn't. I'd built endpoints reactively—whatever worked at the moment. Each endpoint was a unique snowflake. Integration took days instead of hours.

That week, I learned RESTful design isn't about being "technically correct"—it's about building APIs other developers can understand without asking questions.

This article shares the design principles I now use on every API.

Resource Naming Conventions

The foundation of good REST API design is consistent resource naming.

Use Nouns, Not Verbs

Resources are things, not actions. HTTP methods provide the verbs.

❌ Bad (verb-based URLs):

✅ Good (noun-based URLs):

Use Plural Nouns

Collections should use plural names for consistency.

From my production APIs:

Consistency across all resources:

Hierarchical Relationships

Use nested routes to show relationships between resources.

Real examples from my e-commerce API:

Avoid Deep Nesting

Limit nesting to 2-3 levels maximum. Deep nesting becomes unwieldy.

❌ Too deep:

✅ Better:

My rule: If the resource can be accessed independently, give it a top-level endpoint.

URL Structure Best Practices

Use Kebab-Case

Consistent casing improves readability.

❌ Inconsistent:

✅ Consistent (kebab-case):

My implementation:

Versioning

Always version your API from day one.

Three versioning strategies I've used:

1. URL Path Versioning (My Preferred Method)

Advantages:

  • Clear and visible

  • Easy to route to different codebases

  • Cache-friendly

Example:

2. Header Versioning

Client request:

3. Accept Header Versioning

My production choice: URL path versioning—it's explicit and requires no header manipulation.

Query Parameters

Use query parameters for filtering, sorting, pagination, and field selection.

Filtering

Real usage:

Sorting

Usage:

Pagination

Cursor-based pagination (my preferred method for large datasets):

Usage:

Offset-based pagination (simpler, for small datasets):

Usage:

Field Selection (Sparse Fieldsets)

Allow clients to request only needed fields.

Usage:

HTTP Method Usage

Idempotency Matters

Understanding idempotency prevents bugs in production.

Idempotent methods (can be called multiple times safely):

  • GET

  • PUT

  • DELETE

  • HEAD

  • OPTIONS

Non-idempotent method:

  • POST

Real production example:

Why this matters:

Network issues cause request retries. If a client's POST request succeeds but the response is lost, they might retry—creating duplicate orders. My solution:

PUT vs PATCH

PUT: Replace entire resource PATCH: Update specific fields

Real usage:

My preference: PATCH for most updates. PUT rarely needed in practice.

Response Format Consistency

Every response follows the same structure in my APIs.

All my endpoints use this format:

HATEOAS (Hypermedia)

HATEOAS (Hypermedia as the Engine of Application State) includes links to related resources in responses.

Basic implementation:

Response example:

Benefit: Clients discover available actions without hardcoding URLs.

Content Negotiation

Support multiple response formats when needed.

Key Takeaways

  1. Use nouns, not verbs for resource URLs

  2. Plural names for consistency (/users, not /user)

  3. Nest resources to show relationships, but limit depth

  4. Version from day one using URL path versioning

  5. Query parameters for filtering, sorting, pagination

  6. Consistent response format across all endpoints

  7. Understand idempotency to handle retries safely

  8. PATCH for updates, PUT rarely needed

  9. Include metadata (pagination, filters) in responses

  10. HATEOAS links help clients discover API capabilities

Next in series: Building REST APIs with Express.js and TypeScript—hands-on implementation of these principles.


Good API design is about consistency and predictability. Follow these principles, and your APIs will be a joy to work with.

Last updated