Register to get access to free programming courses with interactive exercises

HTTP API Example HTTP API

HTTP APIs can vary significantly, both in HTTP capabilities and the internal structure of the data passed through the API. We'll talk about this in more detail in future lessons, but for now, consider a popular HTTP API variant built on the following rules:

  • Data is passed in JSON format
  • A different URL is used for each data set

It isn't the only way to organize the HTTP API but one of the most common. For example, let's take Dummy JSON — a service for experimenting with APIs. It includes pretend data that you can play around with.

The service documentation describes resources and entities, information about which we can get via APIs. Below is a non-exhaustive list:

URL Description
/posts List of posts
/comments List of comments on posts
/users List of users
/todos Task list

Links we get data through in the HTTP API are endpoints. For example, to get the list of users, you need to download this file from Dummy JSON. You can open it in a browser. The response will return this text (incomplete version):

{
    "users": [
        {
            "id": 2,
            "firstName": "Sheldon",
            "lastName": "Quigley",
            "maidenName": "Cole",
            "age": 28,
            "gender": "male",
            "email": "hbingley1@plala.or.jp",
            "phone": "+7 813 117 7139",
            "username": "hbingley1",
            "password": "1@#4asdfSDF!WER",
            "birthDate": "2003-08-02",
            "image": "https://robohash.org/doloremquesintcorrupti.png?size=50x50&set=set1",
            "bloodGroup": "O+",
            "height": 187,
            "weight": 74,
            "eyeColor": "Brown",
            "hair": {
            "color": "Blond",
            "type": "Curly"
        },
        {
            ...
        }
    ],
    "total": 100,
    "skip": 0,
    "limit": 30
}

The data here isn't real, but it's good enough for us to test. In a real API, we would still need to confirm access because we can't give this data to everyone. In addition, we see the password here, which doesn't happen in real life.

The format in which we pass the data is called JSON. Let's elaborate on that. A format is a way in which data can be packed (serialized) and from which it can be extracted (deserialized).

We also need to think about serialization and deserialization when we pass data from a program to somewhere outside, for example, another program. It is because the data representation is unique within languages, and sometimes even within a particular version of the given language. Therefore, we use more universal formats to transfer data.

In the case of the HTTP API, the service that provides it retrieves the data from the repository, generates JSON, and passes it out. Any program supporting JSON can read this JSON, which any program can do in the modern world. JSON support is often implemented in the programming languages themselves.

JSON is just text. It has a clear structure that we can trace visually. Indentation, spaces, and hyphenation are irrelevant to JSON. The example above might also look like this:

{"users":[{"id":2,"firstName":"Sheldon","lastName":"Quigley","maidenName":"Cole","age":28,"gender":"male","email":"hbingley1@plala.or.jp","phone":"+78131177139","username":"hbingley1","password":"1@#4asdfSDF!WER","birthDate":"2003-08-02","image":"https://robohash.org/doloremquesintcorrupti.png?size=50x50&set=set1","bloodGroup":"O+","height":187,"weight":74,"eyeColor":"Brown","hair":{"color":"Blond","type":"Curly"}}],"total":100,"skip":0,"limit":30}

One might ask, how is this different from transferring data in HTML? HTML is not a data format. HTML is a markup language that generates text for browsers to display as a web page. HTML doesn't involve working with data contained within it. Theoretically, it is possible. But in practice, it'll be difficult.

JSON is not the only data format. Before it, XML was a popular format, and it's still quite common now:

<?xml version="1.0"?>
<Recipe>
   <Name>Lime Jello Marshmallow Cottage Cheese Surprise</Name>
   <Description>
     My grandma's favorite (may she rest in peace).
   </Description>
   <Ingredients>
      <Ingredient>
         <Qty unit="box">1</Qty>
         <Item>lime gelatin</Item>
      </Ingredient>
      <Ingredient>
         <Qty unit="g">500</Qty>
         <Item>multicolored tiny marshmallows</Item>
      </Ingredient>
   </Ingredients>
   <Instructions>
      <Step>
         Prepare lime gelatin according to package instructions
      </Step>
      <!-- And so on... -->
   </Instructions>
</Recipe>

XML, although similar to HTML, has a different function. XML is a data format like JSON, it's not designed for output.

JSON structure

We store data in JSON format inside objects. An object is a piece of data bounded by curly brackets, within which we give keys and their values:

{ "id": 3, "hasBranches": true, "name": "Hexlet", "country": "Finland" }

Keys in JSON are always wrapped in quotes. Values can be numbers, boolean values, strings and null:

  • 1, 3, 2.5
  • true, false
  • "one", "two"

And then there are arrays:

{ "courses": ["php", "ruby", "python"] }

The whole of JSON can only be one array:

["one", "two", "three"]

Objects can be nested in other objects:

{ "id": 3, "hasBranches": true, "name": "Hexlet", "address": { "country": "Finland", "city": "Helsinki" } }

And into arrays:

{ "courses": [{ "id": 1, "name": "php" }, { "id": 2, "name": "javascript" }] }

Metadata

If you look at the /users response structure, you see that the list of users is passed as an array inside an object with additional parameters:

{
    "users": [],
    "total": 100,
    "skip": 0,
    "limit": 30
}

Why not just give the array of users right away?

[{ ... }, { ... }]

The answer here is simple. In addition to the data itself, it's often necessary to transfer some metadata (data about the data), such as the total number of users. If we had an array, we couldn't add this information without changing the structure, going from array to object. Objects allow you to add new data while maintaining backward compatibility in the structure, without breaking it. All you have to do is add a new key to the top level.

Pagination

What if there's a lot of data? For example, there are hundreds of thousands of users on Hexlet. JSON with that much data would be massive. To solve this problem, we have pagination.

Data is not always a whole entity. Sometimes, it can be in small sets. We can see pagination everywhere on the Internet. Remember, for example, the search results in Google, where the result is millions of pages, but only the first ten are shown. The rest is hidden behind other pages.

In the API we work with, we see 30 results by default. You can see in the JSON below:

{
    "users": [],
    "total": 100,
    "skip": 0,
    "limit": 30
}

How do you get the second 30 people in that case? By adding the skip: https://dummyjson.com/users?skip=30

{
    "users": [],
    "total": 100,
    "skip": "30",
    "limit": 30
}

Data limitation

Suppose we don't need all the data, but only some of it. To do this, our HTTP API has a select request parameter: https://dummyjson.com/users?select=firstName,gender

{
     "users": [
        {
            "id": 1,
            "firstName": "Terry",
            "gender": "male"
        },
        {
            "id": 2,
            "firstName": "Sheldon",
            "gender": "male"
        },
        {
            "id": 3,
            "firstName": "Terrill",
            "gender": "male"
        }
    ]
}

Single resource

The parameter /users returns a list of users. If we need one user, we need a different endpoint /users/{id}. This endpoint is called dynamic because it has a part that changes. We replace {id} with the user's ID whose data we want to retrieve.

For example, let us observe https://dummyjson.com/users/9:

{
    "id": 9,
    "firstName": "Demetrius",
    "lastName": "Corkery",
    "maidenName": "Gleason",
    "age": 22,
    "gender": "male",
    "email": "nloiterton8@aol.com",
    "phone": "+86 356 590 9727",
    "username": "nloiterton8",
    "password": "HTQxxXV9Bq4",
    "birthDate": "1971-03-11",
    "image": "https://robohash.org/excepturiiuremolestiae.png?size=50x50&set=set1",
    "bloodGroup": "A+",
    "height": 170,
    "weight": 97.1,
    "eyeColor": "Green",
}

Nested resources

In the services we're looking at here, users can write posts. What if we want to see not the entire list of /posts but the particular user's posts? How do we do that? In this case, we'll use nested resources: https://dummyjson.com/users/3/posts. This endpoint will return all of the user's posts with the ID 3:

{
    "posts": [
        {
            "id": 58,
            "title": "Balloons are pretty and come in different colors",
            "body": "Balloons are pretty and come in different colors, different shapes, different sizes, and they can even adjust sizes as needed. But don't make them too big or they might just pop, and then bye-bye balloon. It'll be gone and lost for the rest of mankind. They can serve a variety of purposes, from decorating to water balloon wars. You just have to use your head to think a little bit about what to do with them.",
            "userId": 3,
            "tags": [
                "american",
                "crime",
                "magical"
            ],
            "reactions": 9727
        },
    ],
    "total": 4,
    "skip": 0,
    "limit": 4
}

The same principle is applied to all other resources:

URL Description
/users/{id}/posts List of a given user's posts
/users/{id}/comments List of the user's comments
/users/{id}/todos List of the user's tasks

Let's look at the big picture

We've learned about one HTTP API with its rules for interacting with endpoints. In other HTTP APIs, it'll be different, but it is up to each developer to decide. What remains unchanged is that we're working through HTTP and using its features.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.