Common Mistakes When Designing APIs
After 5 years of building and consuming APIs, here are the design mistakes I've seen over and over.
/api/proc/getData2
At a previous job, I had to integrate with an API built by an outside vendor. The endpoint was /api/proc/getData2. Nobody knew the difference between getData and getData2, or what proc even stood for. There was no documentation.
That's when it hit me. API design is as important as code -- maybe more.
Verbs in URLs
/api/getUsers, /api/createOrder, /api/deleteItem/3. I built APIs like this when I was starting out too.
In REST, the HTTP method is the verb. The URL should be a noun. GET /api/users, POST /api/orders, DELETE /api/items/3. Simple principle, but I still see APIs that ignore it all the time. Especially internal ones.
Inconsistent Response Formats
Some endpoints wrap everything in { data: [...] }, others return arrays directly. Errors come back as { error: "..." } or { message: "...", code: 500 } -- totally inconsistent.
Frontend developers end up writing different parsing logic for every API. Productivity takes a serious hit.
Defining a consistent response format takes 30 minutes. Skipping those 30 minutes costs dozens of hours down the road.
Sloppy HTTP Status Codes
I've seen APIs that return 200 for everything and stick { success: false } in the body. This makes axios interceptors completely useless.
The other extreme is also a problem. You should distinguish between 422 and 400, or 401 and 403, but there's no need to use 418 (I'm a teapot).
(I actually encountered an API that used 418. Still no idea why.)
Adding Pagination Later
"Let's just return the full list for now and add pagination later."
The problem with this is that when you do add pagination later, every existing client breaks. You should start with { data: [...], meta: { page: 1, totalPages: 10, totalCount: 100 } } from day one. Even if you only have 10 records.
Once an API is deployed, changing it is 10x harder than changing code.
No Versioning
Someone once asked me why we put v1 in /api/v1/users. "We only have v1 right now, isn't it unnecessary?"
Six months later, we needed to change the response format. Because of mobile app compatibility, we had to run two versions simultaneously. If we hadn't had v1, it would've been a disaster.
Returning Too Much Data
I've actually seen a user list API that returned password hashes, internal IDs, and admin notes alongside the regular data. Security issues aside, the response size balloons unnecessarily.
Either return only the fields that are needed, or at minimum, put sensitive data behind a separate endpoint.
In the End, You Have to Invest Time in Design
A good API, in my view, is predictable, consistent, and extensible. To achieve those three things, you need to spend more time on design than implementation.
Not writing a single line of code and defining the interface first is ultimately the fastest path. APIs built in a rush need to be fixed in a rush, and rushed fixes create new problems.