One of the greatest challenges API developers face is creating an API that is flexible enough to pass the tests of time and technology. In other words, creating an API that is built to last. Here are some tips to help you ensure your API has a happy, and long life expectancy – saving you a lot of frustration, and your company a lot of money!
“Unfortunately, people are fairly good at short-term design, and usually awful at long-term design.”
– Dr. Roy Fielding, Creator of REST
The first step to building an API for longevity is understanding that your API should be built to last beyond the current release, and even beyond your current roadmap. You want to build an API that developers can implement fearlessly, without worry that it will change in a few months, or even within a couple years.
After all, there is almost nothing that developers hate more than APIs that are constantly changing – as it breaks their code and destroys their application. In fact, I think more developers are more understanding of bugs than they are of repeated backwards compatibility breaks.
This also means decoupling your API from your application’s services. The API layer should be independent of the tools and technologies that you’re using, letting you update your services or change underlying technologies without impacting the way developers interact with your API.
To build an API for longevity, you must first go in with the mindset that this API will be built to last, meaning you will be releasing major versions only when your current API can no longer meet your application or users needs.
“There really is no substitute for good design”
– Nivi Kumar, Product Manager/ API Team, Vertical Response
A house can only be as strong as its foundation, and the foundation of any API is its design. Usually API design means building out a list of endpoints and then sending your development team to build them. The problem is this usually occurs with developers working in silos, each tackling an endpoint and the JSON response. And while we push for code and pattern reuse in our application, we forget to apply those same principles to our endpoint designs… ending up with uniquely designed and coded endpoints that stray from the design principles our API was founded on, causing confusion among developers in regards to implementation and shortening the API’s life expectancy.
RAML, a new spec that stands for the RESTful API Modeling Language, helps eliminate this problem by allowing you to design your API in the RAML spec, setting up resourceTypes (collections, items), traits (reusable snippets of RAML), and schemas– letting you utilize pattern based design and code reuse to ensure that your API remains consistent in its development.
Like writing code, failure to adhere to the design patterns and structure of your overall API results in spaghetti style endpoints weakens the entire API, forcing you into a corner where eventually you will lose the ability to extend the endpoint when adding additional data and/or integrating services.
“Life is really simple, but we insist on making it complicated.”
While talking to a company about building their API I was astonished when they stated, “we want developers to be confused by our API, so that when they look at it they’ll be impressed by how technologically advanced it is.” Growing up my father would always remind me of the “KISS” principle, or “keep it simple stupid.”
Don’t try to complicate your API. Instead, anything you can do to make it easier to use or understand, do. Use simple URIs that correlate to your application (ie for users: /users), return data that makes it easy for them to understand the response – including content-type. Return header codes that follow HTTP standards (ie 200 ok, 201 created, 405 method not allowed). And make sure you are returning clear error messages when something fails, clearly explaining why the call failed along with links to documentation on how to fix it.
The easier you make your API, the more likely developers will be to use it. And the easier it will be for you to maintain.
“Thinking of behavior and capability rather than process conformance will help organizations deploy and scale their agile adoptions.”
– Mike Griffiths, “It is not the Process, Stupid”
With the flexibility RAML offers, APIs can now be developed in two cycles, first the design stage, and secondly, development. As the industry has moved to the agile methodology, APIs have been plagued with the “what do we want to release, and what do we want to change,” mentality. The problem is, once you release your API it shouldn’t be changing, at least not anything that breaks backwards compatibility. Every change you make in your API should be because of a new feature or new requirement… any other change is nothing more than a failure in the design stage. And while it is impossible to be perfect in the design stage, perfection is what we should strive for in order to minimize making any design related changes in the development stage, including output.
For this reason the API design process should be iterative and as agile as possible. Using RAML to design your API, you can quickly build out the entire system, and with MuleSoft’s free mocking service you can see what the API will look like while letting developers interact with it using mock data. This lets developers test your API out for you, and lets you see how they would actually be using it- helping you quickly identify any changes needed before investing development time into building the API, and more importantly before the API is released into the wild.
Not prototyping or not understanding what your developers want to do with the API is the number one reason I’ve seen APIs fail (or only last a few months). Like any product, you need to understand how your customers intend to use it, and ensure that it is really usable. Take advantage of prototyping and agile user experience in this process.
But once you have a design, it’s time to turn off the tweaks. Similar to test driven development (TDD) you can now do SDD – or Spec Driven Development. While I would encourage the use of iterations as with agile, most of the flexibility agile offers has to go out the door. Your API should not be changing at this point unless you receive substantial information that it no longer works. All the design kinks and bugs should have already been worked out, and trying to build an API with agility ends up creating more problems than it solves, again letting endpoints stray from constrained patterns and into the world of chaos.
“What needs to be done to make the REST architectural style clear on the notion that hypertext is a constraint? In other words, if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API.”
– Dr. Roy Fielding
While there is a fair amount of debate surrounding hypermedia, Dr. Roy Fielding adamantly argues that hypermedia is key to RESTful API longevity – something I personally agree with. Using hypermedia within your API creates a layer of flexibility letting make necessary modifications and add new features seamlessly even after your API has been released. However, it also creates some confusion in that people believe that if they use HATEOAS they can simply change these paths at will, again going back to agile API design. Keep in mind that many paths will be hard coded by developers still, especially top level endpoints as developers will try to cut down on the number of calls to your API to increase performance and reduce the risks of being throttled.
It’s also important to adopt an existing standard for returning available actions to a user such as HAL (Hypertext Application Language). This not only helps developers using your API by providing them with a standardized response, but also helps ensure that you are using a time-tested format that helps prevent the need to go back and make changes to how you return the available actions as this breaks all backwards compatibility.
HAL embedded in a JSON Response (note the _links section):
Using hypermedia also gives you another powerful tool in your arsenal, it lets you develop API wrappers instead of SDKs. While SDKs are powerful, they create an entire new application that developers need to learn, and like any library are now constrained by what the code can do – not by what your API is capable of. Wrappers on the other hand require less time to develop, are more light-weight, and can take advantage of HATEOAS – making calls dynamically based on what the API returns, and then returning that data for developers to use. This ensures that the code you write to help developers get started with your API stays consistent with how your API works, and will last just as long.
“It is easier to resist at the beginning than at the end.”
– Leonardo da Vinci
Change is inevitable, but resist changing your API based on special use cases as much as possible. It’s one thing to add new features, but be very careful when modifying existing endpoints. People will ask for a bunch of features, and a lot of them are going to sound like really good ideas that are fairly easy to implement.
However, while it may seem like a good idea at the time, the more specialized your endpoints become and the more changes you make to existing endpoints, the more likely it is that you are decreasing your API life expectancy, and setting yourself up for an expensive refactor, or worse – building out a new version that forces you to deprecate users, forcing them to either update their code – or jump to a competitor.
Every change should be weighed very carefully, asking yourself does this benefit the majority of the customers? Does it fit in your product roadmap? And, what are the risks of implementing this change? The change should then be incorporated through a design cycle as mentioned previously using RAML with your previously established design patterns, and testing it with developers before releasing broadly to ensure that you are not slowly boxing yourself into a corner and creating a specialized endpoint that operates differently from the rest of your API.
After all, one of the greatest challenges to API versioning is getting developers to use the new version. Remember, it’s better to resist these type of changes right away, no matter how small, as once the flood gates are opened you may find it impossible to say no, or find yourself up a spaghetti endpoint creek without a paddle.
Building an API for longevity requires careful thought, careful design, and extensive prototyping to get developer feedback. Without a solid foundation your API is doomed to be short lived, becoming nothing more than a costly experiment to justify building a better API. This is why the overall design of the API is so crucial to its success, and while tools such as RAML and hypermedia help increase your API’s life expectancy, only with the proper design and mentality can it truly survive the test of time and technology.
Interested in API Design & Best Practices? Join Mike Stowe at API World in San Francisco, or API Strategy in Chicago this September as he talks about the API Lifecycle and ways to make sure your API stands the test of time.
Learn more by checking out Anypoint Platform for APIs »