Designing an API? Try These Techniques to Avoid Future Headaches
Badly designed API infrastructure causes many issues, such as
- The inability to scale or modify the APIs in production.
- Exposing confidential parameters in the URL path.
- Improper naming convention, which leads to confusion.
- Drag in developer cooperation due to confusions & misunderstanding.
- Multiple APIs for accessing the same type of resources.
- Lack of API monitoring tools to analyze and visualize API usage, status, etc.
Therefore, I think it's important to invest time in learning and following some standards and finding some tools for building and analyzing RESTful APIs.
We can't build good, efficient APIs that meet all standards in one day because it's a long-term process that requires a lot of iterations.
Here, I will explain a few standards and rules that everyone can follow to build better RESTful APIs.
Consider this article as a starting point for building efficient, maintainable, and scalable APIs.
Small Mistakes that Cost a Lot
Some problems and mistakes that we are going to discuss here may seem insignificant, but as the product grows or as the customer base increases, these minor mistakes can cause significant headaches.
Addressing these issues, especially without disturbing multiple client applications or causing problems for end users, is the most challenging aspect.
Better Structure, No Confusion
In the long term, having a solid resource naming strategy is a great investment in API design. As features expand, maintaining a proper naming convention helps to avoid confusion in the future and improves readability.
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. “today’s weather in Los Angeles”), a collection of other resources, a non-virtual object (e.g., a person), and so on.
-Architectural Styles and the Design of Network-based Software Architectures by Roy Fielding
Resource Relationship
The fundamental purpose of an API is to provide access to appropriate resources for the user. But what exactly is a resource?
For example, on a blogging platform such as Ghost Blogging Platform, let's check how the APIs are designed.
The main resources on ghost blogging platform includes posts, authors, pages, etc. Each post typically has different attributes, such as:
- id: unique identifier for the blog.
- author: Author of the blog.
- createdAt and updatedAt: Timestamps indicate when the post was created and last updated.
A resource can be in the form of a singleton (a single blog) or a collection (a group of blogs by an author). There is a standard naming convention for singletons and collection resources:
GET /content/posts/
is a collection resource.
GET /content/posts/{id}/
is a singleton resource.
Nouns in URLs
REST-styled APIs are primarily for collecting resources and establishing communication, not for performing actions or operations. Consider these examples:
-
Preferred Approach:
GET /content/pages/
GET /content/authors/
-
Less Preferred Approach:
GET /content/get-blogs
GET /fetch-authors
The first set is clearer and more straightforward. Since it's a GET
method, there's no need to explicitly mention get-blogs
unless it's a RPC-styled method.
Path Parameters
If you are managing a blog platform and need to fetch blogs by a specific author or retrieve details of a book using its identification number, the best practice is to use path parameters.
-
Correct Implementation:
GET /content/authors/{id}/
-
Avoid This Approach:
POST /content/authors/ { authorId: 222 // Incorrect implementation }
Using path parameters like /content/authors/{id}/
provides a clear and structured way to identify resources and their relationships within the API. This approach enhances readability and conforms to RESTful API design principles.
Maintain A Resource Hierarchy
A well-defined resource hierarchy helps define better logical relationships between different components of an API.
Lets consider the same blogging platform, To represent a comment resource of a post, the better hierarchy should look like
/users/{userId}/posts/{postId}/comments/{commentId}
Standards in Request Response Format
APIs have mainly two kinds of responses, Success responses and Error responses.
The main response structure contains this four keys, such as
- Success: return true or false based on response status
- Message: A user friendly message indicating the activity. Or operation
- Data: the main key that contains the data that should be displayed.
- Status code: code for indicating the status of operation or error
Some other best practices are:
- The resource IDs should return an integer.
- Decimal amounts, such as prices or totals, should be returned as strings with two decimal places.
- Instead of omitting blank fields, return null or empty string.
Make API Unbreakable using Versioning
APIs will get modified several times, but this modification does not affect the end user in terms of better API design. versioning helps to maintain robust support and doesnt affect the end user or client application if any major changes occur in the API, such as bug fixing or a feature rollout.
Use API versioning when:
- renaming or changing any endpoint or property
- Parameter changes
- modifying a data format
There are different ways to achieve API versioning, such as
URL Path: Pass the version as a path in the URL, eg: https://journal.hexmos.com/ghost/api/v5/content/posts
Query Parameter: Pass the version as a query parameter along the URL,eg: https://journal.hexmos.com/ghost/api/content/posts?version=v1
Header: Passing version in header is another approach, but it is less transparent compared to version in URL path or as query parameter.
Accept: version=1.0
Tracking the Requests
API monitoring is a crucial step in identifying the usage and request rate of APIs. Better monitoring helps to identify the problems early and fix them before the user reports them.
Some key metrics that we need to monitor every time are:
- API uptime
- Request Rate
- CPU/Memory usage
Let's check out some of the open-source API monitoring tools:
Prometheus
Prometheus collects and stores its metrics as time-series data. By time-series data, we mean metrics that change over time. Prometheus is combined with grafana to create better visualisation.
SigNoz
SigNoz, which has 17k stars on Github, is an open-source observability platform native to OpenTelemetry with logs, traces, and metrics in a single application.
SigNoz supports various features, such as
- Application metrics
- Distributed Tracing
- Log Management
- Exceptions monitoring, etc
Graphite
Graphite can be used to track the performance of websites, applications, business services, and network servers. Similar to Prometheus, graphite also measures time series data.
Security
The Protection of Information in Computer Systems, a paper by Jerome Saltzer and Michael DSchroeder, explains the critical security principles that we can use for the Rest API.
The paper puts forward various principles that we can adapt for REST API security.
-
Least privilege: limits the user's access to rights to what is strictly required to do the job. Principles of Least Privilege (POLP) are adapted to restrict the access of some entities, for example, restricting the employee's access to administrator resources. A time-limit privilege is also given for users to access confidential data for a certain period of time.
-
Use password hashing: It is best practice to hash the password before storing it in database. Hashing algorithms such as PBKDF2, bcrypt, and scrypt algorithms can be used for proper hashing of secrets.
Never expose secrets or tokens in URL. Its's bad practice to expose usernames and passwords. API tokens, session tokens in the URL. -
Validate parameters: Its a good practice to validate the request parameters before processing the application logic.
Conclusion
We discussed very basic, but important, best practices and tools for building a robust API system. As I said before, we cannot build a better system in one day. Making a perfect system should require iterations. But by following the best practices and setting proper rules, it will be easier to maintain and scale APIs in the future.