You've called a REST endpoint from your phone hundreds of times today without noticing it — checking the weather, refreshing a feed, letting an app remember who you are. Ask ten developers to explain what actually happens between the tap and the response, though, and most reach for a definition instead of an explanation. That gap is worth closing, because everything else about APIs stacks on top of it.

💡
The key insight

An API isn't a menu of endpoints — it's a contract that defines who's allowed to ask for what, and how the answer gets shaped.

The Restaurant You Already Understand

A useful way to picture an API is a restaurant, not because it's cute, but because the roles map cleanly onto what's actually happening in your code. You never walk into the kitchen. You hand your order to a waiter, who carries it back, waits while it's prepared, and returns with exactly what you asked for — not the kitchen's entire inventory, not a peek at how the sauce is made.

The API is that waiter. Your app is the customer. The server and its database are the kitchen. The waiter enforces the rules of the interaction: what you're allowed to order, in what format, and what comes back if the kitchen is out of something.

Swap "kitchen" for "database" and the stakes get real. A mobile banking app checking your balance doesn't get direct database access — it goes through an API that decides what's exposed, applies authentication, and formats the response. If the app had raw database access instead, one malformed query from a single user could lock a table and take down balance checks for every other customer mid-payday.

Once you see the API as the boundary that decides what's exposed and how, you stop asking "why can't I just hit the database directly" and start asking "what should this boundary allow, and what should it refuse."

You Use APIs More Than You Think

Almost every app on your phone is doing less original work than it appears to. When an app needs data or an action it doesn't own, it calls an API instead of rebuilding that capability from scratch.

Your weather app doesn't run its own satellites — it calls a weather API. The "Sign in with Google" button doesn't reimplement identity verification — it calls Google's auth API and trusts the token that comes back. A checkout screen doesn't touch your card number directly — it calls a payment provider's API, which returns a token, and the merchant never sees the raw digits at all.

That last one carries real weight. If the payment API call fails silently — a timeout, a malformed response, an unhandled error code — and the checkout flow doesn't catch it, a customer's card gets charged with no order recorded, or an order gets placed with no charge. Either version is a support ticket and a refund, multiplied by however many customers hit that window before someone notices.

Recognizing that most of an app's real work is stitching together other people's APIs changes how you scope what you actually need to build versus what you should call.

What Actually Happens When You Call an API

A request isn't a teleport of data — it's a round trip with real cost at every step, and treating it that way changes how you write the code around it.

The client builds a request: a method, a URL, headers, sometimes a body. That request travels over the network to the server, which routes it to the right piece of code, runs whatever business logic applies, maybe queries a database, and serializes a response. The response — status code, headers, body — travels back, and only then does your code get to act on it.

This matters most under load. If response serialization is slow on a checkout endpoint during a flash sale, connections start piling up waiting for a reply. The thread pool handling those connections gets exhausted, and requests to unrelated endpoints on the same service start timing out too — one slow code path degrades the whole service, not just the feature that caused it.

Thinking of a request as a full round trip, not an instant data fetch, is what makes timeout handling, retries, and error states feel necessary instead of defensive paranoia.

The Verbs: GET, POST, PUT, PATCH, DELETE

HTTP verbs aren't just a naming convention — they're a signal of intent that browsers, caches, and other services rely on to behave correctly.

GET is assumed safe and cacheable: no side effects. POST creates something new. PUT replaces a resource wholesale and is idempotent — calling it twice with the same body produces the same result. PATCH updates part of a resource. DELETE removes it.

The word "assumed" in that first sentence is the trap. A team that wires a GET endpoint to silently increment a view counter breaks every browser prefetch, CDN cache, and search-engine crawler that treats GET as free to call repeatedly without consequence — analytics numbers get inflated by prefetches that never should have counted as real visits, and nobody can figure out why traffic doesn't match conversions.

Pick verbs based on what a client, a cache, or a crawler is allowed to assume about safety — not based on which one happens to be convenient to wire up first.

Not All APIs Are Built the Same Way

REST is the default most juniors learn first, but it's one option among several, each built to solve a different constraint. Picking the wrong one doesn't fail loudly — it just makes everything downstream slightly harder than it needed to be.

REST

Resource-oriented, built on standard HTTP verbs and status codes. It's the default for public web APIs because it's simple to cache, simple to debug with a browser, and every language has a client for it.

GraphQL

The client specifies the exact shape of data it needs in a single request. It solves the overfetching and underfetching problem that shows up on mobile clients pulling from deeply nested relationships — one call instead of five, only the fields actually rendered.

SOAP

XML-based, with a strict formal contract (WSDL) defining every field. It's slower to work with than REST, which is exactly why it survives in banking, government, and legacy enterprise integrations where the contract matters more than developer convenience.

gRPC

A binary protocol over HTTP/2, built for fast internal service-to-service calls where every millisecond of latency compounds across a call chain. It's not meant for a browser tab — it's meant for one microservice talking to another inside the same data center.

Webhook

This one flips the direction. Instead of your app polling "did anything happen yet," the server pushes data to you the moment an event occurs — a payment confirmed, a file finished processing.

WebSocket

A persistent, two-way connection that stays open. Built for anything genuinely live — chat apps, real-time scoreboards, collaborative editors where every keystroke needs to reach every other viewer instantly.

WebRTC

Peer-to-peer, built for real-time audio and video. Two browsers exchange a media stream directly instead of routing every frame of a video call through a central server first.

How Netflix Actually Uses APIs Internally

Netflix's recommendation engine, its user profile system, and its machine learning models aren't one giant service — they're separate internal APIs, each owning its own data and logic, exposing only a contract to the rest of the system.

That separation is a direct, larger-scale application of the boundary discussed earlier. A gateway or frontend composes calls across these services to build what you see on screen, but each one can fail independently.

When the recommendation service has an outage, playback doesn't go down with it. You can still watch a title you already selected, and search still works — only the "recommended for you" row degrades, maybe falling back to a generic popular list, instead of taking the whole app down. That graceful degradation only exists because recommendations were never baked into the playback service in the first place.

The architectural decision of what counts as a separate API versus what lives in a shared codebase directly determines what breaks — and what keeps working — when one part of the system fails.

Status Codes: The Language of What Went Right or Wrong

Status codes exist so a client can react programmatically to what happened, without parsing a human-readable error message first. The ranges: 2xx means success, 3xx means redirect, 4xx means the client made a mistake, 5xx means the server did.

The codes that show up constantly in day-to-day work: 200 (OK), 201 (created), 400 (bad request), 401 (not authenticated), 403 (authenticated but not allowed), 404 (not found), and 500 (server error, something broke).

Getting this wrong is subtler than it sounds. An API that returns 200 with {"error": "not found"} buried in the response body breaks every client's retry logic and circuit breaker, because the client sees success and moves on — no retry, no alert. A real outage starts showing up as healthy green traffic on a monitoring dashboard, and nobody notices until customer complaints do the alerting instead.

Treat status codes as part of the contract, not decoration on top of it — a wrong code doesn't just look sloppy, it silently breaks automation several layers downstream.

Your First Real API Call

The fastest way to build real intuition for APIs isn't a tutorial — it's picking a free public API, making one GET request, and reading the raw response before reaching for a library that hides it.

Seeing the actual shape of a response — headers, status code, raw body — builds the mental model faster than any wrapper SDK, because SDKs are designed to make you forget the request ever happened.

Engineers who skip this step often can't debug an integration failure later, because they've never seen an actual failed response — only the exception message their SDK decided to surface, which is frequently a translation, not the original error.

The first action worth changing isn't "install a package." It's "open a terminal and hit the endpoint directly, and read what comes back before anything wraps it."

From here, every endpoint you touch starts to look like an architecture decision — a boundary someone drew on purpose, with tradeoffs, not an accident of convenience. That's the lens that carries into REST-versus-GraphQL debates, into "should this be a webhook or should we poll" arguments, and into the review comment that asks why an endpoint returns 200 for something that clearly failed.

Free Resource

Get the Junior Engineer Interview Guide

A free PDF breaking down the exact API and HTTP fundamentals questions asked at this level. No fluff, just the patterns that show up in real interviews.

Get the free PDF →