Welcome to Part 2 in our Real World API Series. If you haven't read Part 1 yet, or want to refresh your memory, please follow the link below:
In this post, I am going to hit just a few general API concepts that I have adopted as my own personal best practices over the years. Anyone that has read any of my articles on Developer.com or Internet.com may recognize some of the concepts. If you have ever attended my API Field of Dreams session at a conference, or your company has brought me in to talk to your developers about APIs, you may also recognize some of the content here.
Once again, these are concepts that form one man's opinion, albeit an informed one, built on lessons learned from one man's experiences. You don't have to follow every suggestion to the letter.
Know Your Audience - and Speak to Them
In case you do not realize this, the audience for an API is the development community. I will try to keep this in mind at every step of this series, which will end up producing a real world API, and I suggest you do the same when architecting and developing your own APIs.
I have arrived on this one statement as a guiding principle over the years: when developers use your API, they should feel like they are using something they would have been proud to have written themselves. Keep that thought ever at the forefront, and you cannot go far wrong.
So, how do you speak to developers? Let's imagine the typical use case for an API - Developer X wants to code an application or web site that helps consumers engage your company and either charge money for the application, charge money for site membership or generate enough traffic/usage that advertisements on the site can provide revenue. If your API hasn't been designed with them in mind and doesn't allow them to do that in the shortest time possible, then they will go elsewhere.
I realize that I just, in a circumspect way, told you that your API doesn't have to be perfect -- only better than the other options. If developers think your API is doggie doo, go elsewhere and discover that "elsewhere" is comprised of even smellier doggie doo, they will be back. It's the "safari on foot encounters an angry, hungry lion" problem -- you don't have to be the fastest runner in the safari, just not the slowest.
Hogwash. Let's just go for broke and offer up this advice. Strive for perfection in your APIs. You don't want a developer to discover your API, look around at others and then come back. You want them to fall in love with your API so much that they never leave.
Be Elegant, Intuitive and Compliant
Make your API simple and beautiful. No one wants to use an API with 20 layers of complexity. There will be some more detail later in the post, but for now, let's just agree that we should try to make it look pretty, or at least NOT ugly.
Using your API should be intuitive. Always. Take a look at these two URLs, and think about which one you would rather work with as a developer using an API.
Do you think developers would rather use an API where they can probably guess the URLs or one that comes with a 300-page downloadable PDF to decipher it?
Also, please note the usage of the "api" subdomain in the first URL. I have adopted that as a best practice over the years.
In terms of compliance, if there are already standards in place, don't try to be clever or cute. Just use what is already out there.
The KISS Principle
The military principle of "Keep It Simple, Stupid" should apply at all times. Remember, you want maximum usage by the people that matter. You can still enable complexity, but that should be in the "Advanced Concepts" section.
Strive to make the "Hello World" example developers will use to get up and running as simple as possible. The best way I have found to explain this is the concept of a URL with a Query String. Move the complexity into the Query String. Simple, no? Keep the root level of consuming your API simple, but allow for complexity, not as a mandatory component, but at the discretion of the individual developer.
Let's look at this URL:
Hopefully, you recognize the simpler of the two URLs we presented earlier. However, in the example, by allowing OPTIONAL complexity in the Query String, we have enabled the developer to customize the product field returned, the field to sort the results on, in which order to sort and the total number of products returned.
This kind of complexity can definitely be useful in a real world scenario, where performance matters...but to just return the full provided dataset for all products, the developer can be up and running in just a minute or two with the base URL.
Five Levels Deep
Once again, this is one man's opinion, but a good rule is to keep your API URLs to a maximum depth of 5 levels. Consider the following URL:
Level 1: Base URL (http://api.megalomart.com)
Level 2: Version (v2)
Level 3: Query Object (products) - if you terminate the URL here, assuming a GET request, you will be executing a "Get All Products" request
Level 4: ID (8675309) - adding this level (once again, assuming a GET request) allows you to do a "Get the Product with ID=8675309" request...yes, that IS a Tommy Tutone reference...why do you ask?
Level 5: Query String (fields=id,name,shortdesc,msrp,color,size) - this is where the complexity can, and should, live
In the next section, we will be referencing a Level 3 and Level 4 URL, denoting requests that "Get All Objects" and a "Get One Object", respectively.
Please examine the content below, which shows a generic expected result for Level 3 and Level 4 URLs for the most common HTTP Verbs.
Level 3 URL (http://api.megalomart.com/v2/products)
- GET - returns all products
- PUT - used to bulk update products
- POST - creates a new product
- DELETE - deletes all products
Level 4 URL (http:///api.megalomart.com/v2/products/8675309)
- GET - returns the product with the given ID
- PUT - updates the product with the given ID, if exists; otherwise, error
- POST - error
- DELETE - deletes the product with the given ID, if exists; otherwise, error
You may have noticed that I have used PLURAL NOUNS as my Level 3 URL Entities. This is by design, but also by personal preference. Some folks will take a much more hard-line approach here. My only requirement for my clients is a draconian policy on consistency.
Use nouns or use verbs. Use singular or plural. But be consistent. The last thing a developer needs is to try to guess which entities have an "s" on the end of their Level 3 URL component and which ones do not.
As a plug for my personal preference, I just think it makes sense to use plural nouns. In our example:
- For Level 3 ("Get All") requests, you are returning a list of all Products, so the plural form makes more sense.
- For Level 4 ("Get One") requests, you are returning one of a list of all Products. I guess you could say that you are returning one Product, so the singular form is applicable, but I think it's always better to force developers to remember as little as possible…so the Level 4 requests should build on the Level 3, keeping the same form...so I always keep the plural form and just build on it for Level 4 URLs.
- As for the nouns vs. verbs debate, it just seems that almost all objects/entities in the application and database world are nouns…so why not use nouns to enable developers to work with your business entities?
Let's keep this one short and sweet...and borrow from some of the concepts mentioned earlier.
- Don't reinvent the wheel. The world has figured this out. Let it help you.
- Be compliant. There are widely accepted authentication standards. Use them.
I hope you have learned something from this post that will either help you get started with APIs or make your APIs better. Please stay tuned for Part 3 of the series, where we will introduce the architectural components of our API. Who knows? We might even create and configure some stuff on Azure while we are at it!