Designing an API You’ll Have to Consume Yourself
Building both sides changes the endpoints you write. Here are a few habits I picked up from being my own worst client.

Designing an API You’ll Have to Consume Yourself
There is probably no better way to evaluate an API than having to use it yourself.
When you're building an API from the backend, everything can look fine. The endpoints return the expected data, the queries work, and the responses are technically valid.
Then you start building the frontend.
Suddenly, you realize that one page requires five API requests. A response is missing a field you actually need. Error responses have different structures. Pagination works differently between endpoints.
This is where API design becomes much more than just making endpoints work.
Design for the Consumer
One of the easiest mistakes when designing an API is designing it around the database.
You have tables like:
users
orders
products
payments
So naturally, you create:
GET /users
GET /orders
GET /products
GET /payments
There's nothing wrong with this approach, but the frontend doesn't think in database tables.
It thinks in screens and user interactions.
An order detail page might need customer information, payment details, order items, shipping information, and status. If all of that requires separate requests, the frontend ends up doing the work of assembling a single concept.
The API should be designed with the actual consumer in mind.
Not every endpoint needs to return everything, but it should provide enough information to make the consumer's job straightforward.
Don't Make the Frontend Rebuild Business Logic
Another thing I've learned is that business logic should stay where it belongs.
Imagine the API returns:
{
"price": 100000,
"discount": 10000,
"tax": 9000
}
and the frontend is expected to calculate the final price.
It works, until the business rule changes.
Now every client consuming the API has to know how that calculation works.
Instead, the API could return:
{
"price": 100000,
"discount": 10000,
"tax": 9000,
"final_price": 99000
}
The frontend doesn't need to understand the calculation. It simply displays the result.
I generally like to think of it this way:
The backend owns the meaning.
The frontend owns the presentation.
Consistency Is a Feature
A good API should be predictable.
If one endpoint uses:
{
"data": [],
"meta": {}
}
while another uses:
{
"items": [],
"pagination": {}
}
the frontend now needs different logic for the same concept.
The same applies to:
Naming conventions
Pagination
Error responses
Date formats
HTTP status codes
Null handling
None of these things are particularly exciting, but consistency makes an API much easier to work with.
And an API that is easy to work with is usually a better API.
Errors Are Part of the API
Successful responses are only half of the contract.
The frontend also needs to know what happens when something goes wrong.
Instead of having every endpoint return a completely different error format, establish a predictable structure:
{
"message": "Validation failed",
"errors": {
"email": [
"The email field is required."
]
}
}
Once the structure is consistent, the frontend can handle errors generically instead of creating custom logic for every endpoint.
An API shouldn't only make the happy path easy.
It should make failure predictable too.
The Best Test Is Building Something With It
Documentation and code reviews can tell you whether an API looks good.
Actually consuming it will tell you whether it feels good.
When I build a Next.js frontend against an API I've designed, I quickly discover things I wouldn't have noticed from the backend:
Too many requests
Missing fields
Unclear naming
Inconsistent responses
Difficult error handling
Business logic leaking into the frontend
These problems become obvious because I'm no longer looking at the API as its creator.
I'm looking at it as its consumer.
Final Thoughts
I've found that one of the best ways to design a better API is to ask a simple question:
"If I had to build the entire frontend using this API, would I enjoy using it?"
That question changes a lot.
It encourages simpler responses, consistent conventions, clearer contracts, and better separation of responsibilities.
An API doesn't become good simply because it works.
It becomes good when consuming it feels obvious.
Comments
Nothing here yet. Be the first.