Loading introduction
Loading stats
Loading about
Loading posts
Loading article
Skip to content
Md Nayeem Hossain
Explorer
home.tsx
rest-api-design-best-practices.md
rest-api-design-best-practices.md
blog.json

// Backend

REST API Design: Best Practices and Standards

Learn how to design clean, intuitive, and scalable REST APIs following industry best practices.

Md Nayeem HossainDec 8, 202412 min read

REST API Design Best Practices#

An API is a product for developers. If it's hard to use or inconsistent, developers will hate integrating with it. Good API design is intuitive, predictable, and self-documenting.

Resource Naming#

Use nouns, not verbs. The HTTP method tells you the verb.

text
1Bad:2POST /createNewUser3GET /getAllUsers4 5Good:6POST /users       (Create)7GET /users        (List)8GET /users/123    (Retrieve 123)9PUT /users/123    (Update 123)10DELETE /users/123 (Delete 123)

Using Proper HTTP Status Codes#

Don't just return 200 OK for everything. Use the standard codes to communicate what happened.

  • 200 OK: Success.
  • 201 Created: Resource created successfully (return this after POST).
  • 400 Bad Request: Validation error (client sent bad data).
  • 401 Unauthorized: User is not logged in.
  • 403 Forbidden: User is logged in but doesn't have permission.
  • 404 Not Found: Resource doesn't exist.
  • 500 Internal Server Error: Your code crashed.

Validation with Zod#

Never trust client input. Validation should be the first thing your API does. I recommend using Zod for schema validation in Node.js. It's type-safe and declarative.

typescript
1import { z } from 'zod';2 3const CreateUserSchema = z.object({4  name: z.string().min(2),5  email: z.string().email(),6  role: z.enum(['admin', 'user']).default('user'),7});8 9app.post('/users', (req, res) => {10  // Unsafe input11  const result = CreateUserSchema.safeParse(req.body);12 13  if (!result.success) {14    // Automatically returns a detailed list of what fields were wrong15    return res.status(400).json(result.error);16  }17 18  // Safe, typed data19  const data = result.data;20  // ... create user21});

Pagination#

Never return "all" records. Your database might have 10,000 users one day. Always implement pagination.

typescript
1// GET /users?page=2&limit=202const page = parseInt(req.query.page) || 1;3const limit = parseInt(req.query.limit) || 20;4const skip = (page - 1) * limit;5 6const users = await db.user.findMany({ skip, take: limit });7 8res.json({9  data: users,10  meta: {11    page,12    limit,13    total: await db.user.count()14  }15});

Providing metadata (total pages, current page) helps the frontend build pagination UI easily.

#REST API#Backend#Design#Best Practices
OlderNginx Configuration for Production: Complete GuideNewer TypeScript Advanced Patterns for Professional Developers

Outline

  • REST API Design Best Practices
  • Resource Naming
  • Using Proper HTTP Status Codes
  • Validation with Zod
  • Pagination