WritingCommon REST API Design Mistakes That Slow Down Backend Teams — Clixo
5 min readapi-design, rest, backend, mistakes

Common REST API Design Mistakes That Slow Down Backend Teams

The REST API design mistakes that engineers most often make — from status code abuse to missing contracts — and how to avoid them before they become technical debt.

Most REST API mistakes are not obvious at the time you make them. They look fine in the first sprint and reveal themselves six months later when you have live clients, a second team building against your API, and a backlog of integration bugs.

The mistakes below are common enough to have a pattern. They are also entirely preventable with a small amount of upfront discipline.

The Most Common REST API Design Mistakes

1. Returning 200 for Errors

This is the single most disruptive habit in REST API design. The pattern looks like this:

HTTP/1.1 200 OK
{
  "success": false,
  "error": "User not found"
}

Every client that consumes this endpoint now has to check both the HTTP status code and a custom field inside the body. HTTP clients, proxies, logging tools, and API gateways all treat 200 as success. You are opting out of the entire HTTP middleware ecosystem.

Return 4xx for client errors and 5xx for server errors. The status code is not a suggestion.

2. No Consistent Error Response Shape

When errors look different on different endpoints, clients have to write defensive parsing code for each one. Sometimes it is {"error": "..."}. Sometimes it is {"message": "..."}. Sometimes it is {"errors": [...]}. Sometimes the status code is 400, sometimes 422, sometimes 500 for the same class of problem.

Define an error response schema and apply it everywhere. Document it. Make it the first thing in your API style guide.

3. Encoding Actions in URL Paths

POST /api/users/deactivate
POST /api/sendPasswordReset
GET  /api/fetchUserOrders?userId=42

These are RPC-style paths. REST URLs identify resources. Actions are encoded in HTTP methods. When you need to express a state transition or command, model it as a resource:

POST /users/42/deactivations          — create a deactivation record
POST /password-reset-requests         — create a reset request
GET  /users/42/orders                 — get a sub-resource

This is not pedantry. REST semantics exist because HTTP infrastructure — caches, proxies, gateways — makes decisions based on them.

4. Inconsistent Field Naming Conventions

userId in one endpoint, user_id in another, UserID in a third. This forces clients to maintain a per-endpoint naming map instead of a single deserialization rule.

Pick one convention — snake_case is conventional for JSON APIs — and enforce it in a linter or schema validator. Inconsistency at this level compounds every time a new field is added.

5. Returning Unbounded Collections

GET /users

If this returns every user in the database, it is a ticking clock. The first day it works fine. The day your database has 500,000 users it causes a timeout, an out-of-memory error, or a 30-second response that kills your frontend.

Every collection endpoint needs a default page size, a maximum page size, and pagination in the response. No exceptions.

6. No Versioning Until It Is Too Late

Teams skip versioning because they expect the API to stay stable. It never does. Requirements change, field names turn out to be wrong, response shapes need restructuring. Without a version prefix, every change is potentially breaking.

Starting at /v1/ takes one minute. Retrofitting versioning after you have live clients takes a migration plan, client coordination, and months.

7. Using the Wrong HTTP Method for the Job

  • Using GET for operations with side effects (triggering a job, sending a notification)
  • Using POST for idempotent operations where PUT is correct
  • Using DELETE with a request body to pass parameters

HTTP clients, caches, and proxies make assumptions based on method semantics. A GET request with side effects can be triggered by a browser prefetch. A POST where PUT belongs cannot be safely retried on network failure.

8. Inconsistent Nullability

A field that is sometimes present and sometimes absent is a nullable field in disguise. If an optional field can be missing from the response, document it as nullable. If it is always present, make it always present — never omit it from the response when its value is an empty string or zero.

Clients that parse your responses with strict deserialization will fail on fields that appear and disappear unexpectedly.

9. Floating Point for Money

Representing monetary amounts as float in JSON causes rounding errors that compound over time:

{ "amount": 10.10 }

Use integers (cents/pence) or strings with fixed decimal precision. This is a correctness issue, not a style issue.

10. No Authentication on Sensitive Endpoints (or Inconsistent Auth)

Some endpoints require a Bearer token. Some use an API key. One legacy endpoint has no authentication at all because it was "internal." When authentication requirements are inconsistent, clients build workarounds and security teams find surprises in audits.

Define one primary authentication mechanism. Document which endpoints require which scopes or roles. Treat unauthenticated access to authenticated endpoints as a 401, never a silent permission error.

The Common Thread

Most of these mistakes share a root cause: the API was designed from the inside out, optimizing for what was easy to implement rather than what was clear to consume. The fix is designing from the consumer's perspective first — writing the OpenAPI spec, reviewing what each error response tells a client, and asking whether a new engineer could correctly use each endpoint from the documentation alone.

If you want a production API designed and built with these patterns enforced from the start, talk to the Clixo team.