API

RESTful API Design Best Practices

Build robust and scalable REST APIs following industry best practices.

Plake
Mar 15, 20264 min read683 words
RESTful API Design Best Practices

A well-designed API is a quiet promise to the developers who use it: things will be where they expect, behave the way they read, and break in predictable ways. This guide walks through the conventions that make a REST API feel calm and obvious — even years after it was first written.

URL Structure

Treat URLs as nouns, never verbs. Resources are things; methods describe what you do to them. Pluralise collection paths and keep nesting shallow — anything past two levels gets hard to reason about.

# Good — clear, plural, hierarchical
GET    /api/v1/users
GET    /api/v1/users/42
GET    /api/v1/users/42/orders
POST   /api/v1/orders

# Avoid — verbs in paths, mixed plurality
GET    /api/v1/getUser?id=42
POST   /api/v1/createOrder
GET    /api/v1/user/42/order/list

If a query is filtering or paginating, use query params rather than a new path:

GET /api/v1/orders?status=shipped&page=2&limit=25

HTTP Methods

Each method carries semantic weight. Use the right one and clients can rely on caches, retries, and idempotency without surprises.

Method Purpose Idempotent Safe
GET Read a resource ✓ ✓
POST Create a resource ✗ ✗
PUT Replace a resource entirely ✓ ✗
PATCH Partial update ✗ ✗
DELETE Remove a resource ✓ ✗

Never use GET for state changes. Browsers, proxies, and crawlers will hit the URL again — and you will spend a Friday afternoon debugging duplicates.

Status Codes

Return the most specific code you can. The 200-blob is a smell.

  • 2xx — success. 201 Created after a POST, 204 No Content for empty success bodies.
  • 3xx — redirection. 301 permanent, 302 temporary.
  • 4xx — client error. 400 for malformed input, 401 for missing auth, 403 for forbidden, 404 for not found, 409 for conflict, 422 for validation errors.
  • 5xx — server error. Don’t leak stack traces; log them, return a request id.
{
  "error": "validation_failed",
  "message": "Email is already registered.",
  "request_id": "req_01HQ8X4KZP9YV3F2",
  "fields": {
    "email": "must_be_unique"
  }
}

Versioning

APIs evolve. Decide how, before your first breaking change ships.

  • URL versioning (/v1/, /v2/) — simple, visible, easy to route.
  • Header versioning (Accept: application/vnd.plake.v2+json) — cleaner URLs, harder to debug from a browser.

Pick one, document it, never mix. Promote a v1 to v2 when shapes change; keep both running for a deprecation window of at least six months.

Authentication

Don’t roll your own. Use OAuth 2.0 or JWT for user-facing APIs and signed API keys for server-to-server. Always rotate, always rate-limit, and always log access.

GET /api/v1/me HTTP/1.1
Host: api.plake.studio
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Never accept credentials in query params. They land in access logs, browser history, and your customer-success Slack channel screenshots.

Pagination, Filtering, Sorting

Decide once, apply everywhere. Cursor-based pagination scales better than offset for large datasets, but offset is fine for admin tooling.

GET /api/v1/orders?cursor=eyJpZCI6MTAwMH0&limit=50&sort=-created_at

A consistent envelope helps clients build pagination components without thinking:

{
  "data": [
    /* items */
  ],
  "pagination": {
    "next_cursor": "eyJpZCI6MTA1MH0",
    "has_more": true
  }
}

Documentation

If it isn’t documented, it doesn’t exist. Generate an OpenAPI spec from your codebase — don’t write it by hand. Pair it with runnable examples and a request/response viewer.

Editorial illustration

The best API docs read like a tutorial first and a reference second. Lead with the happy path; let the schema do the cataloguing.

Rate Limiting

Limits protect you from misbehaving clients and protect well-behaved clients from a noisy neighbour. Surface limits in headers so clients can self-regulate.

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 873
X-RateLimit-Reset: 1735689600

Return 429 Too Many Requests with a Retry-After header when limits are exceeded. Be generous on the dashboard; be strict on writes.

Closing Thoughts

A great REST API is mostly restraint. Resist clever shortcuts, keep the surface small, name things twice before you ship them. The boring API is the one developers love a year later.

Share:

About the author

The Plake Team

Writes long-form essays on craft, software, and the slow web. Curates the Sunday digest read by 88,000+ readers.

Read more

Keep reading

Related Articles

Back to AllBack to All
GraphQL vs REST: Choosing the Right API Architecture

Apr 5, 2026

6 min

GraphQL vs REST: Choosing the Right API Architecture

Essential Database Design Patterns for Web Applications

Mar 10, 2026

4 min

Essential Database Design Patterns for Web Applications