REST API Design: Best Practices and Standards
Backend

REST API Design: Best Practices and Standards

M

Md Nayeem Hossain

Author

Dec 8, 2024
12 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.

code
Bad:
POST /createNewUser
GET /getAllUsers

Good:
POST /users       (Create)
GET /users        (List)
GET /users/123    (Retrieve 123)
PUT /users/123    (Update 123)
DELETE /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
    import { z } from 'zod';
    
    const CreateUserSchema = z.object({
      name: z.string().min(2),
      email: z.string().email(),
      role: z.enum(['admin', 'user']).default('user'),
    });
    
    app.post('/users', (req, res) => {
      // Unsafe input
      const result = CreateUserSchema.safeParse(req.body);
      
      if (!result.success) {
        // Automatically returns a detailed list of what fields were wrong
        return res.status(400).json(result.error);
      }
      
      // Safe, typed data
      const data = result.data;
      // ... create user
    });

    Pagination

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

    typescript
    // GET /users?page=2&limit=20
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 20;
    const skip = (page - 1) * limit;
    
    const users = await db.user.findMany({ skip, take: limit });
    
    res.json({
      data: users,
      meta: {
        page,
        limit,
        total: await db.user.count()
      }
    });

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

    REST API
    Backend
    Design
    Best Practices

    © 2026 Md Nayeem Hossain. All rights reserved.