API communication In A Nutshell
Communication. The simple term which’s given to the act of imparting one’s information to another, or rather, an emphasis placed on that simple exchange. It is the medium through which we interact with the world around us.
From catching up with an old friend to something as simple as typing a blog post. You give your laptop information through the keyboard, mouse or what fancy tools you may have at your disposal and it gives you information through the screen.
As fascinating as it may be, you didn’t come here to discuss the intricacies of interactions in life, you came here to learn about APIs. I introduce the concept of communication because it is an important thing to keep in mind as we go forward.
Knowing what an API is and knowing how it works are two completely different things. In my last blog post, I explained what an API is, now I’m going to explain how they work, or rather, how to communicate with them.
As a full stack developer, I’ve been on both sides of the communication channel and I can tell you that understanding the structure of APIs and how they work will give you a sturdy foundation upon which you can enhance your skills.
As the API Consumer, understanding the structure ensures that you make requests that the server can easily understand and process, resulting in the kind of response that you desire.
As the API Developer, it makes it easier for you to develop a more robust system that’s easier to use. The easier it is to use, the less complains you’ll receive. Since you get to dictate just how people get to communicate with you, it becomes all the more vital to understand just how things work. A good API should always tell the API Consumer what they did wrong.
If you’ve read this far, then it is safe to assume you know what an API is, which means you should also understand just how important the client-server communication is. The Client sends a request and the server sends a response. Simple, right? Unfortunately, it’s not.
Real World Communication
To put things into perspective, think about asking your neighbor for some sugar to make your daily ‘elixir of life’, better known as coffee. A simple act we do all too often… unless your a timid introvert like me and would rather waste 15 minutes of your life by going to the store.
Either way, there’s some form of communication that took place and it ended with you walking back into your humble abode with that sweet crystal substance we call sugar, and you can now use it for whatever sweet nefarious purpose your heart desired. I for one cannot survive a day without having my sweet elixir of life (coffee) coursing through my veins.
This is the best case scenario though. You’ve made a great many assumptions here and everything worked out the way you predicted. Things may not always turn this smoothly though.
What happens when your neighbor doesn’t have enough of this crucial ingredient or worse, refused to share their sugar for whatever reason? What happens when you discover the store ran out of sugar or maybe it’s closed? or there’s a storm outside and you can’t go out?
There’s wide variety of things that can happen that end with you returning home empty-handed. Fortunately, regardless of the outcome, you will know the reason for that outcome. Whether it was by exercising your powers of deduction or a sign from the universe, what matters is you returned home with a reason in hand.
Client-Server communication is very much similar to the little scenario I just described above. It seems simple enough at first glance, but once you dive deeper into the profound underlying mechanics that allowed us to get the sugar, you will come to realize that those few seconds (or minutes) were only possible because you’ve been preparing to perform this little task for what may very well be your entire life.
Don’t believe me? Well, it’s all a matter of perspective, it boils down to those underlying mechanics I just mentioned. If you are a parent, aunt or uncle (like myself) try to walk up to that 1 year old you adore so much and tell them that you ran out of sugar and ask them to go get you some more. Now our little scenario just became unimaginably difficult to accomplish.
They’re not that experienced in human interactions or know enough about the structure of modern society that they’d be able to accomplish this little task or return with an equally satisfying reason as to why they couldn’t complete said task.
And that’s essentially the point I’m trying to make. As developers, we can’t just think of API communication as a simple request-response kind of case. We have to be specific in what we want and conversely provide an adequately satisfying response to requests. Things happen and we need to take into account those various scenarios and give relevant feedback to the relevant parties. This form of mindset sets the basis upon which I’ve written this blog post.
In order to improve one’s communication skills, they need to first understand the language and context in which they will use it. As such, understanding the underlying mechanics of these requests and responses that clients and servers send each other is a prerequisite we cannot overlook.
That is, we need to know what tools we have at our disposal in order to use them properly. Without further ado, let’s jump right into it.
API Requests
As you may already know, an API Request is nothing more than a request to a server asking for a particular resource. The request plays a very important part in the whole Client-Server communication in that you, as the client, initiate the exchange of, as such need to specify as clearly as possible what exactly you want.
To create a good API Request, you need to structure it, providing the necessary data, as specified in the API Documentation, in order for the server to be able to understand and eventually give the response you are expecting. The general structure of an API Request follows is as specified in the image below.
Keeping the above image in mind lets try to understand each of these parts using a practical example:
Assume we have some server that people can use to get a list of locations they can get sugar, all you need is to specify how much and the type of sugar they want. Running through the construction of the API Request will help us grasp a better understanding of the desired API Request.
Now, let’s say you want 5 kg of white sugar, the first thing we’ll need is the URI to access the sugar resource and make the request using this URI as our destination address.
URI
The Uniform Resource Identifier (or URI for short) is the single most important part of the API Request. They allow you to specify not only the address of our API but also to the server what resource you want to access. Without this little piece of information, you will not be able to send a request, because quite frankly, where would you say you are sending it to?
Note: URI and URL (Uniform Resource Locator) are not the same thing, a URL is a URI, but a URI is not necessarily a URL. You can follow this link to learn more about this. Since people are more accustomed to URLs I’ll be using that as a substitute for URIs going forward.
Alternatively, if you fail to specify the exact resource on the server you are trying to access, then by default the server will refuse to process your request, returning something like “Error 404: Resource Not Found”, since it does not know what you want.
You can also pass some parameters (or metadata) embedded into the URL that further specify what exactly you want. In light of all this, a standard API Request URL would look somewhat like this:
Whereby http://www.example.com/
is the base server URL, api/resource
is the name of the resource you are trying to access and /value_1/value_2
are the parameters.
Now, back to our little sugar example, the URL for sugar would thus look something like this:
http://www.example.com/api/sugar/white/5000
Where the type of sugar we’re looking for is white and the amount we are requesting is 5000 g (which amount to 5 kg).
This, unfortunately, can get confusing as more parameters are used. People can easily swap the values and confuse the server. In which case the server might read: “white” g of “5000” sugar, instead of “5000” g of “white” sugar.
Enters the Query String!
Another method of passing parameters is to use a Query String. They allow us to specify parameters as key-value pairs chained together using “&”. You can learn more about Query strings here.
Our query string would look like this: ?type=white&amount=5000
We will now be passing our parameters using the query string and append that to the end of the request URL, thus avoiding any confusion the server might have. Our final URL should now look like this:
http://www.example.com/api/sugar?type=white&amount=5000
The next thing we’ll need to specify before sending out little request out into the cyber wilderness is the type of action we want the server to complete for us, and this is where the Method comes into play.
Method
The method is the type of action you want the server to perform. There’s quite a few different API methods that you can send along with your request but the four most commonly used ones are:
- POST: create/save new data.
- GET: retrieve some data.
- PUT: edit/modify existing data.
- DELETE: remove some data.
Here’s list of more methods you probably will never use, I sure haven’t: request methods
Now back to talking about sugar. In our case what we want is a list of locations we can get sugar and as such we will need to tell the server to perform a GET action, which translates to a data retrieval. Once again our little API Request grows closer to the full maturity it’d need so we can send it.
Since we’re using a GET method, there’s only one last thing we need to add and that would be the headers.
Headers
Headers are the part of your API Request that contains metadata about the request. Headers contain a variety of information about both your API Request and Response, respectively.
They carry information about:
- The body of the request,
- Desired characteristics in the response (e.g. desired human language response),
- Details about the request authorization,
- Details about caching, and
- Details about cookies.
Depending on what it is your trying to achieve, will greatly influence which headers to include. You can follow this link to see a list of different HTTP Headers you can use, or this one if you’d simply like to know more about them.
In our case, we don’t need to specify too many headers, given the simplicity of the request. Here’s a short list of headers we’ll include:
- Accept: The acceptable mime type (data type) for the response. e.g. XML, JSON, etc.
- Accept-Language: List of acceptable human languages for the response. This will ensure we don’t receive a response in some language we don’t understand.
- Cookie: A HTTP cookie previously send by the server containing some data.
- Content-Type: The mime type of this content (body). This tells us the format of the document contained.
Since we weren’t sending any data to the server, there is no needs for us to include anything in the body. In the event that we do need to send data, then the body will be needed.
Body
The Body is the part of the request that contains data we want to send to the server. It is here you will place your user’s (your) precious data so it can be sent to the server, processed and saved.
Typically, of the 4 methods I mentioned above, only POST and PUT have a body since they involve sending data to the server. GET and DELETE methods don’t need a body, it suffices to simply tell the server “give me this” or “delete this”.
In the event that we do send a POST or PUT request, then we’d need the body. To give you a practical example of what an API Request Body would look like, here’s a very small JSON object about sugar:
{
quantity: <quantity-in-Kgs>,
type: <type-of-sugar>,
brand: <sugar-brand>,
supplierName: <store-name>
}
In the event that a new store selling sugar pops up, they need to make an API POST Request sending the above JSON as the body value.
And that’s about it. We now have our neatly assembled API Request, all that’s left to do is to send it out into the digital jungle and let it find it’s way to the server, and now we wait…
API Responses
Whenever you expose an API, all it does is sit there and waits… waits to receive a request, and that’s when the magic starts.
Similarly to an API Request, an API Response must also follow a specific format in order for the client to able to interpret the response. The API Response follows a structure as specified in the image below.
Just as we did with the API Response above, we’ll walk through each part of the API Response while trying to construct a response to the request we send above.
For the purpose of keeping things short, we’ll just skip over what happens from when the server receives the request and go straight to building a response to send back.
Status Code
When building a response, the first and probably the most important part we’ll need is the Status Code. It describes the result status of the request that was sent after it was processed. Giving us some much-needed feedback.
Status Codes always take the form of 3 digit numbers. They can be broken down into 5 categories, which are as follows:
- 1xx: Informational Responses
- 2xx: Success Responses
- 3xx: Redirects
- 4xx: Client Errors
- 5xx: Server Errors
You can visit this wiki page to see the full list of all the Status codes. I bookmarked it since I tent to look at it quite often while building APIs, but it can just as easily be Googled. I like to refresh my memory from time to time so I can choose the right status code that will return the most informative response.
It can be quite frustrating when your requests keep getting rejected without knowing why, which is why the status code is so important.
Imagine, you send an API Request to a server and receive a response with a status code along the lines of 4xx, then you immediately know you may have done something wrong with your request and you should probably take another look at the documentation, whereas receiving a status code of 5xx would imply that something went wrong on the server and you should probably let the API Developer know.
Now, back to building a response to the request we build. Assuming our little API Request meets the requirements dictated by the API and has been successfully processed, then our response will have a status code of 2xx, or rather 200: Ok, to be more specific.
This alone will tell us that our request was accepted and processed. We can now proceed to give ourselves a good old pat on the back for being able to communicate what we wanted effectively.
However, if on the other hand, we had forgotten to specify the amount of sugar we wanted, then the server would get confused and return a response with a status code 400: Bad Request. Which is just means the server couldn’t understand what we wanted and we should take another look at the request we send.
Once we have a status code, the next thing we need is a list of some headers that will make it easier for the client to make sense of the response.
Headers
Just as discussed in the request headers section, headers will, in this case, give us more information about the response, as such the headers this time around will be a bit different.
Here’s a short list of some of the common response headers:
- Access-Control-Allow-Origin: Specifies a URI that may access the resource. For requests without credentials, the server may specify ‘*’ as a wildcard, thereby allowing any origin to access the resource.
- Content-Length: The length of the response body in octets (8-bit bytes). This can be used to ensure the data that was sent back from the server was not tempered with on it’s way to you.
- Content-Type: The mime type of this content (body). This tells us the format of the document contained.
- Date: The date and time the response was sent.
- Server: The name of the server that sent the response.
With this information, should we seek to know more about the response we just received, we can just look at the headers.
Now the last thing we need to include before sending this response to the client is the body containing what the client asked for.
Body
Just as discussed above, the body would contain our precious data. If all goes well then the body will contain the list of locations where we can get sugar.
The API Response body will thus look something like this:
[
{
quantity: 10kg,
type: "white",
brand: "Selati",
storeName: "Morning Stock",
},
{
quantity: 5Kg,
type: "white",
brand: "Selati",
storeName: "Pick Fast",
},
{
quantity: 25Kg,
type: "white",
brand: "Sweet Crystal",
storeName: "Woolies",
}
]
And that this it, we’ve now successfully constructed an API Response for the client giving them the information they desired.
Final Thoughts
Communication is the art of information exchange. It’s a process the involves sharing information, processing the information to understand its intent and respond to that intent.
Understanding the structure of requests and responses enables us to not only effectively communicate with APIs but as developers to build more robust communication channels.
I hope you enjoyed this blog post and feel free to leave a comment below, I’d like to hear from you.