If you've built anything beyond a script that only talks to itself, you've probably used an API — even if you didn't fully know why it worked. I want to break down what's actually happens, because once it clicks, a huge chunk of modern software development starts making sense.
What Actually is an API??
Well, it stands for Application Programming Interface for starters.
Simply it lets software talk to each other without needing to know how they work internally.
This isn't limited to "frontend talking to backend." Frontend-to-backend is just the most familiar. This basically means APIs can talk to other APIs and other backends and totally different software. For instance, using a banking app to make a purchase on an online store.
Most web APIs today are REST APIs; they use standard HTTP methods to represent actions on resources:
| Method | Purpose | Example |
|---|---|---|
GET |
Retrieve data | Get a user's profile |
POST |
Create new data | Register a new user |
PUT |
Replace existing data | Update a full profile |
PATCH |
Partially update data | Update just an email |
DELETE |
Remove data | Delete a user account |
Data is usually exchanged as JSON; a lightweight human readable text format.
{
"city": "Kisumu",
"temperature": 24.5,
"condition": "Partly cloudy"
}
The API does not store the JSON; it is just the format in which data travels in for one request or response
Let's call a public API and map the response into a clean data structure:
from dataclasses import dataclass
import requests
# Step 1: Define the shape of the data we expect back.
# This is our data model — think of it as a blueprint for one "weather record."
@dataclass
class WeatherData:
city: str
temperature: float
condition: str
# Step 2: Write a function that makes the actual API call.
def get_weather(city: str) -> WeatherData:
url = f"https://api.example.com/weather?city={city}"
response = requests.get(url) # the actual HTTP request
response.raise_for_status() # raise an error if the request failed
data = response.json() # parse the JSON body into a Python dict
return WeatherData(
city=data["city"],
temperature=data["temp_c"],
condition=data["condition"]
)
# Step 3: Use it.
weather = get_weather("Kisumu")
print(f"{weather.city}: {weather.temperature}°C, {weather.condition}")
The WeatherData does not know or care how it was fetched as you can see from the snippet. It just describes the shape of the data.
response.json() translates the JSON text into a Python dictionary you can use.
raise_for_status() matters because APIs fail, rate limits, bad request and downtime can occur. Always handle that instead of assuming success.
Once you understand APIs as contracts for communication, not as data containers, a lot of architecture decisions become intuitive: why we version APIs, why rate limiting exists, why error handling isn't optional, and why good API design makes or breaks a developer's experience using your system.
Top comments (0)