API Design Tips and Pitfalls

Search for a command to run...

Introduction AWS IAM (Identity and Access Management) roles are the backbone of secure access control in cloud environments. However, managing cross-account IAM roles can quickly become challenging or confusing, especially if you’re missing critical ...

"Kubernetes: Up and Running" by Kelsey Hightower, Brendan Burns, and Joe Beda isn't just a guide; it's an invaluable reference I often lean on in my Kubernetes journey. Though I had ventured into container orchestration before, this book fortified my...

One of my recent reads was "The Pragmatic Programmer" by Andrew Hunt and David Thomas. This guide helps software developers improve their craft. Even after years in software engineering, I believe in continuous learning, especially since technology k...

"Clean Code: A Handbook of Agile Software Craftsmanship" by Robert Martin, often affectionately referred to as "Uncle Bob" in the software community, is an enlightening guide not just for budding engineers but for professionals at any stage of their ...

If you've ever wondered about design patterns in software, 'Dive into Design Patterns' by Alexander Shvets is a great place to start. Shvets makes the topic easy to understand by using real-world examples. He doesn't just talk about ideas but shows h...

Most mobile and distributed applications have an API to plug into quickly, and almost every application uses at least one. Everyone is doing it! But only some people are doing it right. Creating a rich API that can be easily scaled requires planning. Unfortunately, most APIs developed these days, once deployed, can't be changed. Doing so usually breaks the client's code that relies on the API. So while it's good to remain consistent, we should give our APIs room for extension.
We believe API design should follow an open/closed principle: "software entities should be open for extension but closed for modification." Applying this principle will help your API evolve as the industry changes. Here are some of the best practices and pitfalls we've discovered to help you build a great API yourself.
| Method | URI |
| GET | /getAllPhotos |
| POST | /addPhoto |
| PUT | /updatePhoto |
| DELETE | /deletePhoto |
| PUT | /updateAllPhotos |
| DELETE | /deleteAllPhotos |
| GET | /getPhoto |
Developers may be tempted to be as descriptive as possible when structuring API resources. Take, for instance, the table above. Depending on your application's size, using verbs will result in a massive list of URLs. It's hard to keep track of such a list as a developer, but it's even harder for your API consumers as they will need to dig into the documentation for every task. An API should be designed so that users can guess or experiment successfully with the URLs.
| Resource | GET | POST | PUT | DELETE |
| /photos | Return list of all photos | Add a new photo | Bulk update all photos | Delete all photos |
| /photos/3 | Return a specific photo | error | Update a specific photo | Delete a specific photo by identifier |
Above is an example of how we can structure our resources better and make the API easier to use. For example, we only need two resources, /photos and /photos/:id, in conjunction with four HTTP verbs (GET, POST, PUT, DELETE) to be able to perform the operations in our previous colossal list.
Another bad practice is querying the database and dumping everything as an API response. Instead, I recommend using transformers over dumping the database data to the world.
Transformers give you control over what data you output to your API consumers. With transformers, we are confident that sensitive information is not displayed by mistake. Not only is it a security measure, but transformers will also help prevent API consumers' code from breaking when your database schema changes.
While you can build your transformers easily, I recommend Fractal if you are in the PHP world. With transformers, you are afforded the benefit of serializing your data in a specific way and embedding related resources within each other.
While there are more than a dozen status codes, we only need ten codes for REST. Your API consumers will know how to respond to the errors since the status codes are a standard. It would be best if you didn’t make your consumers rely on the error messages to determine how to proceed from an error. Below are the ten status codes you need to use:
| 200 | The request has succeeded |
| 201 | Resource successfully created |
| 204 | Request fulfilled but no content returned |
| 304 | Request not modified |
| 400 | Bad request. Reqeuest can not be understood by the server due to malformed syntax |
| 401 | Unauthorized. The request requires user authentication |
| 403 | Forbidden |
| 404 | Not found. Server can not find requested resource |
| 409 | Conflict. Request can not be completed due to conflict with the current state |
| 500 | Internal Server Error |
So don’t just return HTTP status code 200 for every request.
Apart from returning the correct HTTP status codes, it also helps to return custom error codes and verbose error messages for your API. These will go a long way if you have to offer support to your API consumers. Knowing the error code and message will make it easy to pinpoint the issue in your code.
Are you happy to use an API without documentation? I’m hoping you answered “no.” So while documentation may be painful, you have to do it. Good resource documentation should at least include the following:
Including usage examples and tutorials will be a plus.
Including usage examples and tutorials will be a plus.
Another critical aspect of API design is authenticating and protecting our applications. Below are some strategies you can use to authenticate clients using your API.
This is a standard HTTP authentication mechanism whereby clients supply a username and password BASE64 encoded in the “Authorization” header.
Ouath2 comprise of the following two:
However, since this involves transmitting access tokens and authentication credentials, Oauth2 is only secure if used with TLS/SSL to encrypt data during transmission. You also need to consider storing the client credentials on clients like mobile applications. There is a debate about this, as keeping the credentials for Oauth2 on a mobile or desktop app isn’t the most secure thing to do. If, for instance, our client credentials get compromised, then the Oauth2 provider has to revoke the entire application since we would have that information hard coded.
We have only scratched the surface here. There are a lot of techniques that we could talk about to make our APIs scalable and secure.