An API (Application Programming Interface) is a way for two programs to talk to each other. In web development, you make API calls to send and receive data. The simplest way in JavaScript is the fetch function. You call fetch with a URL, the server sends back data (usually in JSON format), and you use that data in your application. Every modern web application relies on API calls to function.
An API is a way for one program to ask another program for something. That is really all it is.
Here is a non-technical analogy. You walk into a restaurant. You cannot go into the kitchen and cook your own food. Instead, you talk to a waiter. You give the waiter your order (a request). The waiter takes it to the kitchen. The kitchen prepares the food. The waiter brings it back to your table (a response). The waiter is the API. You do not need to know how the kitchen works. You just need to know how to place an order.
In web development, the "restaurant" is a server, the "kitchen" is the backend logic and database, the "waiter" is the API, and "you" are the frontend application. When your React app needs a list of products, it does not reach into the database directly. It sends a request to an API endpoint (a specific URL on the server). The server processes the request, grabs the data from the database, and sends it back as a response.
APIs are everywhere:
Understanding APIs is the bridge between frontend and backend development. It is also one of those concepts that feels abstract until you make your first call. So let us do that.
JavaScript has a built-in function called fetch that makes API calls. Here is the simplest possible example. We are going to call a free public API that returns random user data.
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(data => {
console.log(data.name);
console.log(data.email);
})
.catch(error => {
console.log('Something went wrong:', error);
});
Let us break this down line by line.
Line 1: fetch('https://jsonplaceholder.typicode.com/users/1')
This sends a GET request to the URL. It is asking: "Give me the data for user number 1." JSONPlaceholder is a free fake API that developers use for testing and learning. It returns fake but realistic-looking data.
Line 2: .then(response => response.json())
When the server responds, the raw response is not immediately usable. The .json() method parses it into a JavaScript object that you can work with. Think of it as "translating" the server's response into a format your code can read.
Lines 3 to 5: .then(data => { ... })
Now you have the actual data. data is a JavaScript object with properties like name, email, phone, etc. We are printing the name and email to the console. In a real application, you would display this data on the page instead of logging it.
Lines 6 to 8: .catch(error => { ... })
If something goes wrong (the server is down, the URL is wrong, your internet is disconnected), the .catch block runs instead. Always include error handling. Without it, your application fails silently and you have no idea why.
Try it right now. Open your browser, press F12 to open Developer Tools, click the Console tab, paste the code above, and press Enter. You should see a name and email printed in the console. You just made your first API call.
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
When you make an API call, the data comes back in a format called JSON (JavaScript Object Notation). Here is what the response from our example looks like:
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"phone": "1-770-736-8031",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net"
},
"address": {
"street": "Kulas Light",
"city": "Gwenborough",
"zipcode": "92998-3874"
}
}
If this looks familiar, it should. JSON looks almost identical to a JavaScript object. It uses key-value pairs wrapped in curly braces. Keys are always in double quotes. Values can be strings, numbers, booleans, arrays, or nested objects.
Once the .json() method parses the response, you access the data using dot notation:
data.name // "Leanne Graham"
data.email // "Sincere@april.biz"
data.company.name // "Romaguera-Crona"
data.address.city // "Gwenborough"
JSON is the standard format for API responses across the entire web, not just JavaScript applications. Python, Java, Go, and every other language can read and write JSON. When you learn to work with JSON in JavaScript, you are learning a skill that transfers to every language and every API you will ever use.
One common beginner mistake: trying to access JSON data before it has been parsed. If you skip the .json() step and try to read response.name, you will get undefined because the raw response object does not have a name property. Always parse first, then access.
The .then() syntax works, but there is a cleaner way to write the same code. It is called async/await, and it makes asynchronous code read like synchronous code.
Here is the same API call written with async/await:
async function getUser() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const data = await response.json();
console.log(data.name);
console.log(data.email);
} catch (error) {
console.log('Something went wrong:', error);
}
}
getUser();
Let us break this down.
async function getUser(): The async keyword tells JavaScript this function contains asynchronous operations (things that take time, like API calls).
const response = await fetch(...): The await keyword pauses the function until fetch finishes and returns the response. Without await, the code would continue before the response arrives, and you would be trying to read data that does not exist yet.
const data = await response.json(): Parsing JSON also takes a moment, so we await that too.
try/catch: This is the async/await version of .catch(). If anything inside the try block fails, execution jumps to the catch block.
Both styles (promises with .then() and async/await) do exactly the same thing. Async/await is generally preferred in modern code because it is easier to read and debug. You will see both in tutorials and codebases, so it is worth understanding both. But if you are writing new code, use async/await.
Not all API calls are the same. There are four main types, and each one does something different.
GET: Retrieve data. "Give me the list of products." This is the default. When you call fetch(url) without specifying a method, it is a GET request.
POST: Create new data. "Here is a new user, save them." POST requests include a body (the data you are sending).
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'My First Post',
body: 'This is the content of my post.',
userId: 1,
}),
});
const data = await response.json();
console.log(data);
Notice the second argument to fetch: an options object. method: 'POST' tells the server you are sending data, not requesting it. headers tells the server the data is in JSON format. body contains the actual data, converted to a JSON string with JSON.stringify().
PUT: Update existing data. "Change the title of post number 5." Structurally similar to POST, but with method: 'PUT' and a URL that identifies the specific resource to update (like /posts/5).
DELETE: Remove data. "Delete post number 5."
await fetch('https://jsonplaceholder.typicode.com/posts/5', {
method: 'DELETE',
});
These four operations (GET, POST, PUT, DELETE) map directly to the four database operations (SELECT, INSERT, UPDATE, DELETE). This is not a coincidence. Most APIs are designed to be a thin layer over database operations. Understanding this connection makes both APIs and databases easier to learn.
Every beginner hits these. Knowing them in advance saves you hours of debugging.
Forgetting to parse the response. The fetch response is not your data. It is a Response object. You need to call .json() to get the actual data. If you try to read response.name instead of parsing first, you will get undefined.
Not handling errors. APIs fail. Servers go down. Internet connections drop. URLs change. If you do not have a .catch() or try/catch block, your application breaks silently and you have no idea why. Always handle errors, even if your handler just logs the error to the console.
Forgetting that fetch does not throw on HTTP errors. This trips up a lot of people. If the server returns a 404 (Not Found) or 500 (Server Error), fetch does not throw an error. It treats it as a successful response. You need to check response.ok manually:
const response = await fetch(url);
if (!response.ok) {
throw new Error('Server responded with ' + response.status);
}
const data = await response.json();
CORS errors. You will eventually see an error like "Access to fetch at 'x' from origin 'y' has been blocked by CORS policy." This is a security feature. Browsers block requests from your frontend to a different domain unless the server explicitly allows it. It is not a bug in your code. It is a server-side configuration issue. For learning purposes, use APIs that have CORS enabled (like JSONPlaceholder) or add a proxy through your development server.
Sending JSON without the right headers. When making POST or PUT requests, always include 'Content-Type': 'application/json' in your headers and use JSON.stringify() on your body. Without these, the server receives garbage instead of structured data.
Trying to use API data before it arrives. API calls are asynchronous. If you call an API on line 1 and try to use the data on line 2 without await or .then(), the data will not be there yet. The code runs line 2 before the API has responded. This is the most common source of "undefined" errors in beginner code.
The best way to learn APIs is to use them. Here are free, public APIs that are perfect for practice projects.
JSONPlaceholder (jsonplaceholder.typicode.com): Fake REST API for testing. Returns posts, comments, users, and todos. No API key needed. This is the one we used in our examples. Perfect for your first project.
Open Weather Map (openweathermap.org/api): Real weather data for any city. Requires a free API key (you sign up and they give you a key to include in your requests). A weather app is a classic beginner project because it combines an API call with user input and data display.
REST Countries (restcountries.com): Data about every country (population, capital, flag, languages). No API key needed. Good for building a country explorer or trivia game.
The Dog API (thedogapi.com): Random dog images. No API key needed for basic use. Simple and fun, good for practicing image display.
PokeAPI (pokeapi.co): Data about every Pokemon. No API key needed. Surprisingly rich data set that is good for practicing nested data structures and pagination.
A good first project: Build a page that fetches data from one of these APIs and displays it. Add a search input that lets the user filter or find specific data. Add loading and error states. This single project teaches you fetch, async/await, JSON parsing, DOM manipulation (or React state management), and error handling. It covers most of what you need to know about APIs as a beginner.
Once you are comfortable calling other people's APIs, the next step is building your own. That is when you start learning backend development with Node.js and Express. For a broader view of how APIs fit into the full picture, see our guide on what full stack development means.
KES 2,999
Not sure where to begin? This beginner-friendly course covers how computers work, the internet, Git, and your first lines of code — everything you need before picking a stack. 10 modules, 89 lessons.
Start Tech Foundations