My name is Dipesh Sapkota, and as a Computer Engineering student, I've found that one of the best ways to understand abstract concepts is to build something tangible.
When you start learning web development, the term API (Application Programming Interface) appears everywhere. You encounter endpoints, HTTP methods, status codes, and JSON responses. These concepts can seem theoretical until you use them to make a real application communicate with a server.
To explore these concepts in practice, I built Sportivo, a sports-focused web application. Working on this project gave me an opportunity to understand how web applications request data, process responses, and handle communication failures.
In this article, I'll explain the fundamentals of APIs, HTTP requests, JSON, and error handling through practical examples inspired by Sportivo.
What Is an API in a Web Application?
An API provides a defined way for different software components to communicate with each other.
Imagine you're at a restaurant. You choose something from the menu, give your order to the waiter, and the waiter communicates it to the kitchen. Once the food is ready, the waiter brings it to you.
A web API works in a similar way:
- Client: The frontend requesting information.
- API endpoint: The address where the request is sent.
- Server: The system that processes the request.
- Response: The information or result returned to the client.
In a sports application such as Sportivo, the frontend might need fixture information, team details, or live scores.
Rather than maintaining every piece of sports information independently, an application can request it from an external sports data provider. The provider processes the request and returns data that the application can use.
The exact process depends on the API architecture and data source, but the underlying idea remains the same: APIs establish a structured way for software systems to communicate.
Understanding an HTTP Request
When a web application requests data from an API, it commonly uses HTTP, the protocol that defines how clients and servers exchange requests and responses.
Let's break down the main components.
1. The Endpoint
An endpoint is a specific URL through which an API exposes a resource or operation.
For example:
https://api.example.com/v1/fixtures/live
This is a fictional endpoint. A real sports API would provide its own base URL and endpoint structure in its documentation.
An application might use an endpoint like this to request information about live fixtures.
2. The HTTP Method
The HTTP method describes the intended operation.
Common methods include:
- GET: Retrieve information.
- POST: Submit data or request that a resource be created.
- PUT: Replace a resource.
- PATCH: Update part of a resource.
- DELETE: Request the removal of a resource.
For example, Sportivo might use a GET request to retrieve match information.
fetch("https://api.example.com/v1/fixtures/live");
This sends a request using the default GET method.
The endpoint and method must match what the actual API supports.
3. Request Headers
Headers provide additional information about an HTTP request.
Depending on the API, headers may specify the expected response format, authentication credentials, or other request metadata.
For example:
const response = await fetch(
"https://api.example.com/v1/fixtures/live",
{
method: "GET",
headers: {
Authorization: "Bearer YOUR_API_KEY",
Accept: "application/json"
}
}
);
Here, Authorization demonstrates one common way to authenticate an API request.
The example uses a placeholder rather than a real credential. Actual authentication requirements vary between providers.
A security note: If an API key is intended to remain secret, don't place it in frontend JavaScript that users can inspect. Route requests through a backend that securely stores the credential instead.
Understanding API Responses and JSON
Sending a request is only half of the process. The application must also understand the response.
An HTTP response generally contains:
- A status code.
- Response headers.
- A response body, when applicable.
Common status codes include:
| Status code | Meaning |
|---|---|
200 OK |
The request succeeded. |
201 Created |
A resource was created successfully. |
400 Bad Request |
The request was invalid. |
401 Unauthorized |
Authentication is missing or invalid. |
403 Forbidden |
The server refuses the requested operation. |
404 Not Found |
The requested resource wasn't found. |
429 Too Many Requests |
The client exceeded a rate limit. |
500 Internal Server Error |
The server encountered an unexpected problem. |
Many web APIs return their data as JSON (JavaScript Object Notation).
JSON is a text-based data format commonly used to exchange structured information between applications.
For example, a fictional sports API might return the following response:
{
"match_id": "98765",
"status": "In Progress",
"home_team": {
"name": "Arsenal",
"score": 2
},
"away_team": {
"name": "Liverpool",
"score": 1
},
"minute": 74
}
This example illustrates a possible response structure; it isn't a verified live response from a particular sports provider.
The nested objects represent the two teams, while the status and minute fields describe the match.
In JavaScript, you can access these values after parsing the response:
console.log(data.home_team.name);
console.log(data.home_team.score);
console.log(data.away_team.name);
console.log(data.away_team.score);
If data contains the example above, the output would be:
Arsenal
2
Liverpool
1
This is how an application can transform a structured API response into information that makes sense to a user.
Making an API Request with JavaScript
Let's combine these concepts into a complete example using JavaScript's built-in fetch() function.
The following example uses a fictional endpoint. To run it against a real service, replace the endpoint and configure the authentication required by your provider.
async function getLiveScores() {
try {
const response = await fetch(
"https://api.example.com/v1/fixtures/live",
{
headers: {
Accept: "application/json"
}
}
);
if (!response.ok) {
throw new Error(
`HTTP Error: ${response.status} ${response.statusText}`
);
}
const data = await response.json();
console.log("Live scores:", data);
return data;
} catch (error) {
console.error("Failed to fetch sports data:", error);
return null;
}
}
getLiveScores();
Let's understand what happens here.
-
asyncallows the function to useawait. -
fetch()sends the HTTP request. -
await responsewaits for the response to become available. -
response.okchecks whether the HTTP status is in the200–299range. -
response.json()parses the response body as JSON. -
catchhandles errors that occur during the request or subsequent processing.
Notice that fetch() does not automatically throw an error for HTTP responses such as 404 or 500. Checking response.ok is therefore important.
This example handles failures by logging the error and returning null. A production application would generally need a more informative user interface, appropriate retry behavior, and more detailed error handling.
Why Error Handling Matters
Networks are unreliable, servers experience outages, and APIs enforce usage limits.
Without appropriate error handling, a failed request can leave an application displaying incomplete information or an endless loading indicator.
Consider several situations:
1. Network failure
The user's connection drops, or the server cannot be reached.
2. Authentication failure
An API credential is missing, expired, or invalid.
3. Rate limiting
The application sends more requests than the provider permits.
4. Unexpected response data
The API changes its response structure, or the application receives data it wasn't designed to process.
Each situation may require a different response.
For example, a user-friendly application could display:
Live scores are temporarily unavailable.
Please try again later.
The application could also preserve previously retrieved information when appropriate, show when the data was last updated, and offer a retry option.
However, it should not present old information as if it were current. This is particularly important for live sports data, where accuracy and timing matter.
Connecting These Concepts to Sportivo
Working on Sportivo provided a practical context for understanding how a sports application can organize data and present it to users.
The broader workflow of an API-powered application looks like this:
- The user opens the application.
- The frontend requests the information it needs.
- The relevant server processes the request.
- The application receives a response.
- JavaScript processes the returned data.
- The interface renders the information for the user.
- If a request fails, the application handles the failure appropriately.
In a more complex architecture, the frontend may communicate with a backend service, which then communicates with an external API. This can help protect credentials, centralize validation, and control how requests are made.
The exact architecture depends on the implementation. Not every application uses a separate backend, and the examples in this article illustrate general API concepts rather than documenting Sportivo's complete production architecture.
That distinction is important: understanding the general pattern is useful, but a project's actual architecture should always be described based on its real implementation.
What I Learned
Building and exploring practical web projects has reinforced several lessons for me:
- An API is a contract: The client must follow the provider's documented endpoints, methods, authentication rules, and response format.
- A successful request isn't the entire job: The application still needs to validate and process the returned data.
- Error handling is part of the design: Network failures and unsuccessful HTTP responses should be expected.
- Security matters: Secret credentials must be protected, and backend validation is important when handling untrusted input.
- Documentation saves time: Understanding the API's requirements before writing integration code makes debugging easier.
The biggest takeaway is that APIs become much easier to understand when you connect the theory to a practical application.
You don't need to understand every part of a complex system before starting. You can begin with a simple request, inspect the response, handle errors, and gradually build more sophisticated functionality.
Explore My Work
If you're interested in the projects I'm building and the lessons I'm learning along the way, you can explore my work here:
- GitHub: github.com/Dszae
- Sportivo: Explore the Sportivo project
- Personal portfolio: dipeshsapkota7.com.np
You can explore the available source code, review the implementation, and follow my progress as I continue learning and building.
I'm Dipesh Sapkota (dszae), a Computer Engineering student at IOE Thapathali Campus in Nepal, interested in AI/ML, practical software projects, and creative technology.
I plan to keep documenting what I learn, including the problems I encounter, the solutions I test, and the lessons that other developers might find useful.
If you're learning about APIs, I'd encourage you to build a small project of your own. Start with one endpoint, understand its response, and make something useful with the data.
That's where the concepts start to make sense.
Top comments (0)