Skip to main content

How to Build a REST API with Best Practices

Build a resource-oriented REST API with correct HTTP verbs and status codes, boundary input validation, consistent Problem Details errors, and path-based versioning for safe evolution.

Difficulty
Beginner
Duration
45 minutes
Steps
6

What and why

REST models your domain as resources addressed by URLs, manipulated with HTTP verbs. A well-designed REST API is predictable: clients can guess routes, rely on status codes, and parse consistent errors. This tutorial builds a small resource API the right way.

Prerequisites

  • A runtime and web framework (Node with Express or Fastify here).
  • Basic HTTP knowledge.
  • A data store, or an in-memory list for the demo.

Steps

1. Model resources and routes

Use plural nouns and let the verb carry the action:

GET    /v1/articles        list
POST   /v1/articles        create
GET    /v1/articles/:id    read
PATCH  /v1/articles/:id    partial update
DELETE /v1/articles/:id    delete

Avoid verbs in paths (no /getArticles).

2. Implement CRUD handlers

app.post('/v1/articles', (req, res) => {
  const article = create(req.body);
  res.status(201).location(`/v1/articles/${article.id}`).json(article);
});

3. Use correct status codes

200 for success, 201 for created (with a Location header), 204 for a successful delete with no body, 400 for bad input, 404 for missing resources, 409 for conflicts, and 422 for semantic validation errors.

4. Validate request input

Validate at the boundary with a schema and reject invalid bodies before any logic runs:

const schema = z.object({ title: z.string().min(1), body: z.string() });
const parsed = schema.safeParse(req.body);
if (!parsed.success) return res.status(422).json({ errors: parsed.error.issues });

5. Standardize error responses

Return a consistent error shape, ideally RFC 9457 Problem Details:

{ "type": "about:blank", "title": "Not Found", "status": 404, "detail": "Article 7 does not exist" }

6. Version the API

Put the major version in the path (/v1/) so breaking changes ship as /v2/ without affecting existing clients. Keep responses backward compatible within a version: add fields, never remove or repurpose them.

Verification

  • Each route returns the documented status code.
  • Invalid input returns 422 with field-level errors.
  • A 404 returns the standard error shape.
  • The version prefix is present on all routes.

Next Steps

Document the API with OpenAPI, add pagination and filtering to list endpoints, secure it with JWT or OAuth, and add rate limiting before exposing it publicly.

Prerequisites

  • A runtime and web framework
  • Basic HTTP knowledge
  • A data store or in memory list

Steps

  • 1
    Model resources and routes
  • 2
    Implement CRUD handlers
  • 3
    Use correct status codes
  • 4
    Validate request input
  • 5
    Standardize error responses
  • 6
    Version the API

Category

API Design