DEV Community

Bernadette Akinyi
Bernadette Akinyi

Posted on

How Software Actually Talks to Software

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"
}
Enter fullscreen mode Exit fullscreen mode

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}")
Enter fullscreen mode Exit fullscreen mode

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)