Top 9 Tips for Creating Outstanding APIs


Some things never change, like how amazing it feels to use a beautifully designed API.
I imagine it’s the same feeling Apple users always talk about🙄… it just works, intuitively, right out of the box.
Some of the APIs I’ve personally used that really capture this quality are:
GitHub API - Beautiful, well organized, loads of examples and status indicators, super stable.
Twilio API - A toddler could use it with all the tutorials they have written for it👶.
On the other side of things, you can read Casey’s blog or this reddit post about Splitwise’s API to get a sense of the rabbit hole bad API design can drag you into.… Being on the receiving end of such an API is like trying to save burnt rice by drowning it in sauces to mask the flavour. You know you have little chance of success, but you try it anyway because you’re down bad and it’s your only option.
Creating clear, concise, and consistent REST API endpoints is essential for usability, maintainability, and scalability. Here are some tips for creating RESTful API endpoints that make sense:
Stick to Standards
Use standard HTTP methods (
GET
,POST
,PUT
,DELETE
, etc.) appropriately. For example,GET
for retrieving data,POST
for creating data,PUT
orPATCH
for updating data, andDELETE
for removing data.Make use of the Standard HTTP status codes to represent the status of the request. For instance,
200
for success,400
for bad request,404
for not found,500
for server errors, etc.
Use Nouns in URLs
Name your resources using nouns, not verbs.
Good:
/users
Bad:
/getUser
If possible, use plural nouns (e.g.,
/orders
,/products
).Sticking to this means your URLs should give an idea about the resource without being overly verbose.
Nest Resources for Hierarchies
If there's a relationship between resources, you can nest them.
- Example:
/authors/123/books
to get books by a specific author.
- Example:
Make sure you avoid Deep Nesting, which can be hard to read and might indicate your resources are too coupled. Limit nesting to one or two levels if possible.
See Below on when to use Nesting vs Filtering
Use Query Parameters for Filtering
If you want to provide options for filtering, sorting, or selecting specific fields, use query parameters.
Example:
/products?category=electronics&sort=price-asc
Version Your API
Including a version number in your API endpoint can help maintain backward compatibility. Trust me, even if it feels unnecessary right now, it’s 100% worth it in the long run.
- Example:
/v1/users
- Example:
Provide Clear Error Messages
When returning errors, provide a clear message, an error code, and, if applicable, a reference to the relevant documentation section.
🚫The opposite of this? An API that throws the wrong error code for the issue you’re facing. Like returning a 400 when, in reality, the server is spiraling into a deranged crash loop and should definitely be hitting you with a 500.think
Document Your API
A well-documented API, possibly with tools like Swagger or a Postman collection that users can download, is invaluable. It helps users understand endpoints, request-response formats, error codes, etc. And the interactive element allows them to test this in real time swiftly
💡TIP: A lot of frameworks can automatically generate Swagger docs or Postman collections for you, saving time and ensuring consistency.
Support Pagination for Large Data Sets
When returning large lists, please, for the love of all developers out there, use pagination to break up the results.
- Example:
/users?page=2&limit=50
- Example:
Be Consistent
- Whatever conventions you decide to use, be consistent throughout your API. This makes it much easier for developers to predict endpoint names and functionality.
Remember, while it's important to stick to conventions, there's no one-size-fits-all approach to designing API endpoints. The needs and contexts of applications can differ widely. Tailor your API design to your application's specific requirements, while keeping these best practices in mind.
For more info on this topic I recommend ByteByteGo’s video
When to use nesting vs filtering?
GET /users?id=123
or GET /users/123/
Both filtering and nesting are common patterns in RESTful API design, and each has its place depending on the context. Here's when you might consider using each:
Filtering:
Filtering is useful when:
You're dealing with collections: When you're retrieving a subset of a collection based on specific criteria, filtering is the way to go. For instance, you might want to get all orders made in the last week, or all users who joined after a certain date.
Example:
GET /orders?startDate=2023-01-01&endDate=2023-01-07
GET /users?joinedAfter=2023-01-01
Multiple criteria: Filtering shines when you need to combine several criteria.
Example:
GET /products?category=electronics&priceBelow=100
Optional parameters: Filtering works well when parameters can be optional. Using the above example, you might want to filter just by category or just by price.
Nesting:
Nesting is useful when:
You're expressing a hierarchy or ownership: Nesting is often used to indicate a relationship between resources. It clearly denotes that one resource is a subset or owned by another.
Example:
GET /users/123/orders
- Get all orders for user 123.GET /books/456/chapters
- Get all chapters for book 456.
Avoid ambiguity: In some scenarios, you might want to avoid confusion between resource identifiers and filter parameters. Nesting can help here.
Example:
- Suppose
orders
can also be identified by alphanumeric strings like "special-order". In such a case,GET /orders/special-order
could be mistaken for a filter if using the?id=
pattern. ButGET /orders/special-order/items
is unambiguous.
- Suppose
Resource-specific actions: Sometimes, actions or methods are specific to a resource and make more sense when nested.
Example:
POST /users/123/reset-password
- An action specifically for user 123.
Combining Both:
In many cases, it's actually quite sensible to combine both filtering and nesting to achieve more granular control.
Example:
GET /users/123/orders?status=shipped
- This nests to get orders for a specific user and then filters those orders to get only the ones that have been shipped.
Bottom Line:
Use filtering when dealing with a broad collection and you want to narrow down the results based on certain criteria.
Use nesting when you want to denote hierarchy, ownership, or a clear relationship between resources.
In the case of your example (GET /users?id=123
vs. GET /users/123/
):
GET /users/123
is more conventional for retrieving a specific resource by its identifier.GET /users?id=123
is a filter on theusers
collection, but in this specific use case (retrieving by ID), it's more conventional and clear to use the nested format.
Here are five examples for both scenarios:
When to use Nesting:
Author and Their Books
- To fetch all books written by a specific author:
GET /authors/123/books
This indicates a clear hierarchical relationship between an author and their books.
- To fetch all books written by a specific author:
User and Their Orders
- To retrieve all orders made by a particular user:
GET /users/456/orders
This indicates that the orders belong to or are associated with a specific user.
- To retrieve all orders made by a particular user:
Blog and Its Comments
- To fetch comments for a specific blog post:
GET /blogs/789/comments
The nested structure communicates that you're interested in the comments associated with a specific blog post.
- To fetch comments for a specific blog post:
When to use Filtering:
Search Products by Category
- To fetch products in the "electronics" category:
GET /products?category=electronics
Instead of nesting, filtering provides a flexible way to query products based on various attributes.
- To fetch products in the "electronics" category:
Filter Users by Registration Date
- To get users who registered after a certain date:
GET /users?registeredAfter=2023-01-01
Filtering is ideal here because registration date isn't a hierarchical or ownership relationship.
- To get users who registered after a certain date:
Search for Articles Containing Keywords
- To retrieve articles containing the keyword "AI":
GET /articles?keyword=AI
Keywords can vary, and filtering allows querying based on dynamic content.
- To retrieve articles containing the keyword "AI":
In summary, nesting is particularly useful when there's a clear hierarchical or ownership relationship, while filtering is ideal for narrowing down collections based on varying criteria.
Subscribe to my newsletter
Read articles from Bosire Nyakundi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
