Software Engineering · Deep dive

Designing APIs

An API is a promise other people build on, and the moment they do, its shapes are yours to keep. This guide is how to choose those shapes well — the style, the resources, the errors, the way it changes without breaking — so a service other teams depend on stays easy to use and safe to evolve. Worked through one running example: the public API for Snip, the URL shortener from Designing for Scale.

A stable surface over a changing systemclientAPI · /v1POST /linksGET /links/{code}PATCH /links/{code}GET …/clicksstable · versioneddepends ondbcachequeueimplementation — free to changeevolve by addingv1 { code, url }+ tagsadd fields · never remove or rename · new /v2 only on a real break

A good API hides a system behind a handful of shapes a stranger can guess. The caller does not see your database, your queue, or the three services behind the gateway; they see links they can create, read, and delete, and clicks they can page through. Every choice in this guide is about that surface: what the shapes are, what the words mean, what happens when something goes wrong, and how you add to it for years without breaking the code already written against it.

The hard part is not the first version. It is that an API is forever: once another team ships code that calls POST /v1/links and reads code out of the response, that field is a contract, and removing it is an outage you caused on someone else's schedule. So the discipline here is designing for the second version from the start — additive change, clear errors, versioning you can actually execute — and being deliberate about the few decisions that are expensive to reverse.

How to read this guide

Chapters build in order: the surface first, then how it changes, then how it is protected, then one worked design. A first read front to back pays off, but if you are short on time, pick a path:

New to API design

Read 00 → 04 in order — the style, the resources, the collections, and errors. That is a usable API. Then read 05 (versioning) before you ship, because the first version is the one you are stuck with.

Building a public API

Skim 01–03, then read 05 (versioning), 06 (auth), 07 (rate limits) and 08 (idempotency) closely — these are what separate an internal endpoint from an API strangers can depend on. 09 when you need events.

Design review or interview soon

00, 02, 04, 05, and 08, then 10 as a dry run. These are the decisions a reviewer will push on: resource shape, error model, how it evolves, and how a retry stays safe.