Skip to main content

APIs

An API (Application Programming Interface) is a contract: a defined set of requests a client is allowed to make of a service, and the responses it can expect back, without needing to know anything about how that service is actually implemented. It's the same idea as a function signature, just exposed across a network boundary instead of within one process — and that network boundary is what turns "just call a function" into an entire module's worth of design decisions.

Most APIs on the web ride on top of HTTP/HTTPS: a client sends a request with a method, a path, headers, and optionally a body, and the server replies with a status code, headers, and optionally a body. Everything else in this module — gateways, REST vs. GraphQL, idempotency, rate limiting — is really about refining pieces of that one basic exchange.

The contract is the point​

The value of an API isn't the code behind it — it's that the client and server can change independently as long as neither breaks the contract. A team can rewrite their entire service's internals, swap databases, or rearchitect from a monolith to microservices, and as long as the API's requests and responses stay the same, every client keeps working without a single line of its own code changing. This decoupling is what makes horizontal scaling practical at an organizational level, not just a machine level: teams can scale independently the same way servers do, because the API is the stable interface between them.

System Design Lab

Breaking the contract — renaming a field, changing what a status code means, removing a parameter — breaks every client that depends on it, which is why API versioning and backward compatibility (covered in API Design) are treated as first-class engineering concerns, not an afterthought.

HTTP methods carry meaning​

Part of the contract is which HTTP method is used for which kind of operation. Interviewers notice when a candidate says "the client sends a POST and gets back a 201" instead of "the client saves the data" — it's more precise, and it signals fluency with the actual protocol:

MethodPurposeTypical success status
GETRetrieve a resource, no side effects200 OK
POSTCreate a resource, or trigger a non-idempotent action201 Created
PUTReplace a resource entirely200 OK / 204 No Content
PATCHPartially update a resource200 OK
DELETERemove a resource204 No Content

Some of these methods carry a stronger guarantee than just "does the thing": GET, PUT, and DELETE are specified to be idempotent — calling them once or a hundred times should leave the system in the same state — while POST generally isn't. That distinction turns out to matter a lot for retry logic, and gets its own full treatment in Idempotency.

Status codes as a contract too​

The status code range tells the client, at a glance and without parsing a body, roughly what happened:

  • 2xx — success. The request was understood and processed.
  • 3xx — redirection. The client needs to look somewhere else.
  • 4xx — client error. The request itself was malformed, unauthorized, or asked for something that doesn't exist — retrying it unmodified won't help.
  • 5xx — server error. Something broke on the server's side; a retry might succeed.

That 4xx/5xx split is a genuinely useful piece of design vocabulary: it's the difference between "the client should fix its request" and "the client can safely retry as-is," which is exactly the kind of distinction a well-designed retry policy (and later, Rate Limiting's 429 status) depends on.

APIs aren't only for external clients​

It's easy to picture an API as "the thing a mobile app calls," but internally, every service-to-service call in a microservices architecture is also an API — and often a more heavily used one than anything a human client hits directly. Treating internal calls with the same contract discipline (explicit versioning, stable error formats, documented expectations) is what keeps a large distributed system's services independently deployable instead of secretly coupled through undocumented behavior.

Why this matters in an interview​

Naming an API's shape explicitly — "the client hits POST /orders, gets a 201 with the new order's ID" — is a small habit that consistently reads as more senior than describing the same interaction in prose. It also forces you to notice the harder questions early: is this operation idempotent, does it need to be paginated, what does the error response look like — all of which are exactly what the rest of this module works through in detail.

Designing behind a stable API contract: pros and cons​

Pros

  • Client and server evolve independently as long as the contract holds
  • Hides implementation details, so internals can be rewritten freely
  • Gives teams (and services) a clear, testable boundary of responsibility

Cons

  • Any breaking change to the contract breaks every client depending on it
  • Requires upfront design discipline — naming, structure, and errors are hard to change later
  • Versioning and backward compatibility become ongoing maintenance work

Further Reading​

Share this lesson

Saved locally in your browser — visible in the sidebar as you go.