
API design rules are simple habits that keep an API clear, predictable and reliable for every app that uses it. They are not an official standard. They are lessons experienced backend developers have collected, often after an outage they would rather not repeat.
This guide walks through those rules in order. It covers why an API is a contract, how to name resources, what HTTP methods and status codes really mean, how to version safely, and how to validate input, explain errors and paginate large lists. It finishes with one request that follows every rule, and the three mistakes that break APIs most often.
- An API is a promise: the same request should keep getting the same kind of answer.
- Name resources with plural nouns like /users, and let the HTTP method describe the action.
- Return honest status codes: 2xx means it worked, 4xx is the caller's mistake, 5xx is the server's fault.
- Put breaking changes in a new version, such as /v2, and retire old versions with notice.
- Validate every request, explain errors clearly, and send large lists in pages.
- 0:00Intro
- 0:25An API is a contract
- 1:14The four API laws
- 1:59Clear, consistent resource names
- 2:59HTTP methods mean something
- 3:59Status codes tell the truth
- 4:45Version your API
- 5:39Validate input, explain errors
- 6:31Paginate large lists
- 7:25One request, every law
- 8:15Three mistakes to avoid
- 9:02Four laws, one promise
- 9:29Treat your API like a promise
Why is an API a contract?
An API is a promise about what callers can send and what they will get back. Picture one front door that many apps walk through every day. A mobile app, a web app and a partner's app all send requests to your API, and your API reads and writes the database. They all depend on that door behaving the same way each time.
When the promise is kept, the same request gives the same kind of answer today and next year, and nobody has to rewrite anything. When it is broken, the damage spreads quietly. Rename one field in a response and all three apps feel it at once. A team you have never met may have built on your API, and their users could start seeing crashes overnight.
The rules in this guide fall into four laws. Law one is clear names. Law two is giving HTTP methods and status codes their real meanings. Law three is versioning. Law four groups validation, helpful errors and pagination. Senior developers care about these because they have lived through the outages the rules prevent. Following them lets you skip that pain.
- Law 1: clear, consistent resource names
- Law 2: HTTP methods and status codes that mean what they say
- Law 3: versioning
- Law 4: validation, helpful errors and pagination
How should you name API endpoints and resources?
Law one starts with the address. Every URL should name a resource, meaning a thing your API manages, such as users, orders or products. The usual convention is plural nouns, applied the same way everywhere. Good names let developers guess how your API works instead of studying it.
In the example below, GET /users lists all users and GET /users/42 fetches one user. Adding /orders to that path returns that user's orders, and POST /orders creates a new order. Every path names a thing, and the method says what to do with it.
Why nouns and not verbs? The HTTP method already describes the action, so a path like /getUsers says it twice. It also invites drift. Soon you might also have /fetchUsers and /listUsers, and nobody can tell which one to use. One pattern applied everywhere is the real benefit: once someone understands /users, they can correctly guess how /orders and /products behave without opening the docs.
- Use plural nouns: /users, not /getUsers
- Nest related things: /users/42/orders
- Keep the same pattern across every resource
# Plural nouns, consistent everywhere
GET /users
GET /users/42
GET /users/42/orders
POST /orders
What do GET, POST, PUT, PATCH and DELETE mean?
Law two says how to act on those named resources. HTTP already provides verbs, called methods, and each one has an agreed meaning. The URL names the thing; the method says what to do with it. Think of a library book: it is the same book whether you borrow it or return it. Same URL, different method, different action.
GET reads. Calling GET /users/42 fetches that user and must never change data, so it is always safe to call again or to cache. POST creates. Sending POST /orders with the order details adds a new order, and the server usually replies with its new ID.
PUT updates an existing resource by replacing it with what you send. Its cousin PATCH changes only a few fields, such as a user's email address. DELETE removes a resource, so DELETE /users/42 deletes that user. Because each method has one clear job, any developer reading a request knows what it will do.
- GET: read data, never change it
- POST: create a new resource
- PUT: replace an existing resource
- PATCH: edit a few fields
- DELETE: remove a resource
Which HTTP status codes should an API return?
The other half of law two is status codes. Every response starts with a three-digit number that tells the client what happened before it even reads the body. Client apps check that number first, so it has to be accurate. Honest codes let apps react correctly without a human stepping in.
Here are three requests and their answers. GET /users/42 returns 200 OK with the user. A POST with a badly formed email returns 400 Bad Request, because the input was wrong. GET /users/999 returns 404 Not Found, because that user does not exist.
Knowing the groups covers most cases. Codes in the 200s mean the request worked. Codes in the 400s mean the caller made a mistake. Codes in the 500s mean the server failed. The groups also tell apps whether trying again might help: retrying a request with a bad email won't fix it, but a server-side failure might be worth another attempt.
- 2xx: it worked (200 OK)
- 4xx: the caller's mistake (400 Bad Request, 404 Not Found)
- 5xx: the server's fault
How do you version an API without breaking clients?
APIs change over time. Law three makes sure those changes never surprise existing clients. The usual method is versioning: putting a label like v1 in front of your endpoints. It works like an app that keeps its old version running until everyone is ready to move.
An older app keeps calling /v1/users while a newer app calls /v2/users. Both can be served by the same users service behind the scenes, so the real logic lives in one place and only the contract differs.
A breaking change, such as renaming or removing a field, belongs in a new version. Adding an optional new field usually isn't breaking, so v1 can safely receive it. When v1 finally has to go, retire it gently. Announce a date, warn clients early and give them time to move. Handled this way, a risky change becomes a planned upgrade.
- Renamed or removed fields mean a new version
- Optional new fields can usually go into the current version
- Announce a shutdown date before turning old versions off
How to validate API input and write helpful error messages
Law four has three parts, and the first two belong together. Check every request before acting on it, and when something is wrong, explain exactly why. Validation works like a bouncer at the door: nothing gets inside your system without being checked.
Follow one bad signup. A POST /users request arrives. The API checks the fields and finds the email is "anna@", with nothing after the @ sign. The rule fails because there is no domain. Instead of saving broken data, the API replies with 400 and a clear message.
A helpful message names the field, the problem and the fix. For example: "email must include a domain, like anna@example.com." The developer can fix that in seconds instead of guessing. Never trust input, even from your own app. Catching bad data at the door costs far less than cleaning up a messy database later.
- Validate every field before acting on it
- Reject bad input with a 4xx code, not a silent save
- Error messages should name the field, the problem and the fix
What is API pagination and why does it matter?
The last part of law four is about size. Once your app holds a very large number of users, sending them all in one response is slow for everyone. Pagination means sending the list in small pages, one at a time, the way you read a book chapter by chapter rather than all at once.
In the example below, the client asks for GET /users with page two and a limit of twenty, which returns users twenty-one to forty. The response holds those twenty users, and a next field points to page three, ready for the following request.
Small pages load quickly and use less memory, and they stop one giant request from slowing down everyone else on the server. The next link matters too. Clients never have to build page URLs by hand. They follow the link until there isn't one. That keeps the API fast however large the data grows.
- Accept page and limit parameters
- Return a next link so clients know where to go
- Stop when no next link is returned
GET /users?page=2&limit=20
# returns users 21-40
{ "data": [ ...20 users... ],
"next": "/users?page=3&limit=20" }
One request that follows every rule
Here is how the four laws work together in an everyday request. Anna is building a shop app and needs to show the first page of users. She sends GET /v1/users with page set to one, and it reaches the shop API.
Inside, a version check routes the request to v1. Validation confirms that the page value is a real number. The API then fetches only twenty users, one page's worth. The reply is 200 OK with twenty users and a next link. That one request uses a plural noun, GET for reading, a version prefix, checked input, a paginated list and an honest status code. Anna gets what she expected on the first try.
Common API design mistakes and how to fix them
The same three slips appear again and again, even in popular APIs, and each has a simple fix. The first is verbs in URLs, like /getUsers. Use nouns plus methods instead: GET /users. The second is returning 200 OK with an error hidden inside the body, so apps think the request worked. Use real codes such as 400 or 404.
The third is silent breaking changes. Put them in a new version and announce it early. Before shipping anything, ask one question: would this surprise an app that already uses my API? If the answer is yes, it needs a fix or a new version.
- Verbs in URLs: use nouns plus HTTP methods
- 200 OK with an error inside: use real error codes
- Silent breaking changes: release a new, announced version
Key takeaways
- Treat your API as a promise to every app that depends on it.
- Use plural nouns for resources and let methods describe the action.
- Send honest status codes so apps can react automatically.
- Put breaking changes in a new version and retire old ones with notice.
- Validate input, explain errors clearly and paginate large lists.
Frequently asked questions
Should REST API endpoints use nouns or verbs?
Use nouns, usually plural, such as /users or /orders. The HTTP method already states the action, so a verb in the URL repeats it and tends to produce inconsistent names like /getUsers and /fetchUsers.
What is the difference between PUT and PATCH?
PUT updates a resource by replacing it with the data you send. PATCH changes only some fields, such as updating just a user's email address.
Is it okay to return 200 OK with an error message in the body?
No. Apps check the status code first, so a 200 tells them the request succeeded even when it failed. Return a real code such as 400 for bad input or 404 for a missing resource.
When do I need a new API version?
You need one when a change would break existing clients, such as renaming or removing a field. Adding an optional new field usually isn't breaking, so it can go into the current version.
Why paginate API responses?
Sending a huge list in one response is slow and puts load on the server for everyone. Small pages with a next link stay fast and let clients move through the data one step at a time.