Intro to APIs

What if we wanted to make a weather application? We could build the user interface, meaning the outward appearance of our app, but ultimately if we wanted to make an app that told people about the weather, we would need weather data. How would we get that? Hire a team of meteorologists? Create our own weather service? Think ahead to our Yelp clone, how are we going to get the restaurant data that we need for it?

Let's talk now about APIs, which are the engine behind any application that relies on special data or services to add functionality that developers can do on their own.

Working with APIs will account for likely the largest amount of async code that you will write in your applications. APIs our apps powerful, interesting and dynamic. But let's take a step back. You may be saying at this point that the APIs sound very mysterious and ambiguous. What is an API?

What is a API / REST API?

A lot of the confusion that developers have regarding APIs and what they are exactly is that the acronym is used so often to describe incredibly different things.

Let's start with a formal definition: the acronym API stands for Application Program Interface, and its a means for software to communicate with other software. APIs are used by all programming languages, so they are not just limited to JavaScript. But as it concerns JavaScript, we've already been working with APIs.

For example, take the window object that we can access globally. As we've seen, it gives us a ton of properties and methods to help us create our apps. The entirety of those features we can use, which we haven't even come close to covering is the API. APIs can be relatively small, too, however, like the Geolocation feature on the window. That too can be referred to as an API in itself, the Geolocation API.

Improved API Definition

So don't be confused when you see API in the future, it just means the stuff a tool provides to help us build apps. In a word, a helpful service.

REST API

But returning to our weather app or Yelp clone example, what API do we use for that. When it comes to getting a specific type of data that is external to our app, we can often use a special API called a REST API. If you can think of a type of data, a REST API has been made for it. And to get that data, we use JavaScript to make a network request, also known as AJAX requests.

We'll cover both REST APIs and network request hands-on, in-depth in this lesson.

CRUD corresponds to HTTP methods

The acronym CRUD refers to how data is commonly used in applications--we create, read, update and delete it.

Fortunately REST APIs give us the equivalent of all of these operations when it comes to working with remote data. You can see the equivalents summarized within this table here:

To create a new piece of data with a REST API, we have to perform a POST request. POST is the name of the HTTP method, which is a piece of data that tells the API what we want to do. So sending a request with the POST method will cause the REST API to create a new resource. If we just want to get a resource from the API, we use the GET method. If we want to update a resource or bit of data that already exists, we use either the PUT or PATCH method. And to delete a resource remotely, we perform a DELETE request.

Action HTTP Method Description
Create POST Creates a new resource
Read GET Retrieves a resource
Update PUT/PATCH Updates an existing resource
Delete DELETE Deletes a resource

POST/PUT/PATCH require request body, GET/DELETE don't

As a side note, both POST and PUT/PATCH requests usually require data to be provided on the request to be able to create or update the resource. While GET and DELETE requests just require the either the GET or DELETE method to be provided, without any data, to get or delete a certain piece of data, respectively.

When do you use APIs?

When do you need to interact with APIs like these? Simply put, when the app calls for it. You may have a basic app like the Google Keep Clone that we created, where we don't have to interact with the outside world at all. But in the next project, since we're going to be getting restaurant data, obviously we don't have that, so we'll rely on an API to give that to us. If you need some sort of data, any kind of data, it's almost guaranteed that public API exists for it that you can use to build your app around.

How to use an API

If you're unfamiliar with REST APIs and making network requests to them, I'm going to give you the fastest lesson in them you'll ever get. Ready? We're going to use a REST API right now. Here's what you need to do, go to this address:

http://jsonplaceholder.typicode.com/posts

Boom. You just used an API that gives us post data from a blog.

It may have looked strange to you, going to a page that likely looks like a blob of data, but that's what interacting with a REST API is like. We make a network request, and the simplest way to do so is by using our browser, which performs a GET request and it's returned to us.

JSON

The data that we got back is JSON data, which is primary format that data is sent over the web through these requests. It stands for JavaScript object notation and looks very similar to standard JavaScript objects, but are not exactly the same. We'll see how to easily convert data to and from JSON.

Fetch API

Now instead of using our browser, obviously, we need to use JavaScript, and to make all of our different kinds of requests, we are going to use a relatively new tool available on the window API called fetch().

Like our browser, fetch requires the url that we want to make a request to. This url is known as an API endpoint.

Let's look at the documentation for the API that we just used called JSONPlaceholder. If you want, you can check it out on the home page at jsonplaceholder.typicode.com documentation image.

We can see all of the routes or possible endpoints that we can make requests to here as well as the appropriate HTTP method to use for each of them. REST APIs will always include the same HTTP methods, GET, POST, PUT and DELETE, but the names of their routes will be specific to that API, so make sure to look at the documentation for guidance:

So let's make a get request to the /posts/1 endpoint to fetch a single blog post.

GET requests

If you want to just get some data, you want to perform a GET request, which is the simplest request to make with fetch. All you have to do is to execute fetch as a function and the first argument it accepts is the endpoint we want to get data from:

fetch(endpoint);

So for our first request, lets provide the posts/1 route

​fetch('https://jsonplaceholder.typicode.com/posts/1');

And that's it! But how do we get our data? We can see how if we just console.log the request:

console.log(​fetch('https://jsonplaceholder.typicode.com/posts/1'));

We see that it's a promise! So you see that we don't have to write promises on our own. They are baken into many tools or libraries like fetch, particularly if we need to work with data from a REST API.

So to get our retrieved data, if the request was successful, we use then. But what does it give us? Well for every request we make, we get back a response, which is an object that includes a lot of information. For succinctness, most developers just shorten this to res. If we wanted to look at the res, we could just console.log it:

​fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(res => console.log(res))

However we're not done writing our request yet. In virtually all cases when we need the response back from the request, we want the data know as it called the response body, which is, to put it more simply, is the stuff that we wanted in making the request. In this case, the first post.

However the response body isn’t always in the form we need. We often need convert it to a format JavaScript can handle.

Fortunately, fetch() contains a number of methods which help us convert the response body data to a usable format. In this case, because you know you’re getting JSON, you can convert the body to JSON data by calling json() on the response. Make sure to call this as a method at the end. This is a common error when using fetch is to use json just as a method.

The method also returns a promise, so you’ll need another then() method. In this then, we get our actual data, which we could either name data or json:

​fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(res => res.json())
  .then(data => console.log(data))

//   {
// ​ userId: 1,
// ​ id: 1,
// ​ title: ​'First Post'​,
// ​ body: ​'This is my first post...'​,
// ​};

We see that our data is provided to us as a simple JavaScript object. So now we can interact with this data just like we would any normal JS object, like get properties off of it, just as the title property:

fetch('https://jsonplaceholder.typicode.com/posts/1').then(res => res.json()).then(data => console.log(data.title));

If this seems a bit confusing at first, don't worry. We're going to get a lot of experience making network requests with fetch, so by the end of the course writing them will come natural to you.

Of course there are other ways of interacting with the JSON placeholder API as we saw, so let's make some other types of network requests with fetch.

POST requests

Most of your requests will be simple GET requests. But you’ll eventually need to make more complex requests. What if you wanted to add a new blog post? If we refer to the API documentation again, we see that there is a route /posts that accepts POST requests. Again the entire endpoint will be: http://jsonplaceholder.typicode.com/posts.

If we are making a lot of requests this endpoint will be tedious to have to write everytime, so let's us template literals and interpolation to help us out.

Since the base part of the url isn't going to change, just the route at the end, let's store the first part of the url in a variable called baseUrl:

const baseUrl = "http://jsonplaceholder.typicode.com";

And then using template literals we can combine the variable with the route:

fetch(`${baseUrl}/posts`);

That's a lot cleaner and will make these easier to write.

fetch(`${baseUrl}/posts`);

So far, we've only supplied one argument to fetch()—the endpoint. That's because the default type of request or method as it is called, for fetch is a GET request. For anything else we need to pass an object of configuration options as a second argument.

Since we're making POST request, we'll declare that our method is POST. Additionally, since POST creates a new resource, and we want to make a blog post, we need to provide that data with the request, specifically as JSON data. Additionally, we need to tell the API that we are sending over JSON data. To do that we put a special string on the request called a header, which tells the data or content type we're sending over. Content-Type set to application/json.

Finally, you’ll need the body. And if we look at the rest of the documentation, we'll see that to create a resource with POST, we need to use an object .

const​ blogPost = {
  title:'Cool Post',
  body:'alksmdfaklsmflkamsdflkamsflmaslfd',
  userId: 1,
};

And since this is just a normal JavaScript object, we need to convert it to JSON, which we can do with JSON.stringify.

const baseUrl = 'http://jsonplaceholder.typicode.com'
​ ​const​ options = {
  ​ method:'POST',
​   headers: {
  ​ ​'Content-Type':'application/json',},
​ body: JSON.stringify(blogPost),};fetch(`${baseUrl}/posts`, options)
.then(res => res.json())
.then(data => console.log(data));
​
 ​// {​
​ ​// title: 'Cool Post',​
​ ​// body: 'alksmdfaklsmflkamsdflkamsflmaslfd',​
​ ​// userId: 1,​
​ ​// id: 101​
​ ​// };​

If your request is successful, you’ll get a response body containing the blog post object along with a new ID.

So if we were to compare the GET request that we made with fetch versus the POST request, the main difference is just this second argument, an object, which includes the method, appropriate headers and request body.

Error handling with response.ok

What if we have a problem with our request, for example if we provide the right domain but spell the end of the endpoint incorrectly? Let's try making a GET request to a nonexistent endpoint and see what happens:

​fetch('https://jsonplaceholder.typicode.com/pots/1')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(error => console.error(error))
// GET 404

The fetch() promise will resolve even if you get a failing status code. Here it gives us a 404 response, which means that the resource or bit of data waasn't found. So if we have a failed request, it's not going to run the catch callback. So to have catch handle the failed request, we need to detect the error ourselves.

To do that, we can use a property that comes back on the response called ok. This will be set to true indicating a successful response if it is a status code in the 200 range. So 200 something status codes means successful request. If it's not in the 200 range, and ok is false, we can assume the request failed.

So it looks like this:

if (!response.ok) {
  throw new Error("Oops!");
}

We can throw an error to run our catch callback and for the message that we pass to it, we can provide our own message, but a better approach is to include the status code from the response because it gives us actual information about why the request failed. What is helpful about these three digit status codes is that the number gives us clear information about why the request failed. We're not going to go deep into status codes, but what you should generally know about error status codes, is that any error that has a code in the 400 range means a problem with how the request was made (which might be our, the programmer's or the user's fault), and a 500 range code means the server had a problem (which means it is not our fault)

if (!response.ok) {
  throw new Error(response.status);
}

Other request data than JSON

While JSON data is probably the most common data type sent on requests, there are other data formats that we can include on our requests, such as FormData, which is used for making POST or PUT requests with data from an HTML form. Beyond that, there are even more methods for customizing your request.

Closing

So that is GET and POST, the two requests you're going to be making the most when working with APIs. We're not going to explore how to make requests with all of the HTTP methods. Rest assured, we'll cover PUT and DELETE later on in the course.

Challenge

For now, we're going to get more familiar with making basic GET requests to REST APIs.

Go to https://github.com/public-apis/public-apis and find any API you like. This is a huge list of APIs that you can work with and features every sort of data you can imagine. Go through the table of APIs to play around with, and find one that gives you some data that interests you, one where in the auth category it says the text 'no' (which means you don't need any authentication or API key to use it) and make at least 5 (preferably different) requests to it.

The API documentation may look confusing at first, but try to find an endpoint that you can make GET requests to. Also, learning how to read documentation is a very important step of becoming a developer. It is a skill that requires experience.

So get comfortable working with using fetch and go through the various APIs documentation, knowing what you do now about REST APIs. It might be the start of your next big JavaScript project