Chapter Three · Designing the API
Designing the API
Stagedoor's API grew one endpoint at a time, and it shows: verbs in the URLs, dates in three formats, prices as floats, errors as "something went wrong," and a page 400 that returns the same order twice while buyers check out. Seven topics redesign the surface as resources with typed shapes, parsed once at the edge, with errors a client can act on, pagination that stays correct under writes, changes that need no version, and an honest account of what gRPC and GraphQL would have bought instead.
The surface Marek inherited had thirty-one endpoints named after the functions that served them: POST /doHold, GET /getSeatsForEvent?id=, POST /cancelOrder. Dates came back in three formats depending on which handler wrote them. Prices were floats, and three seats at 1999 cents became euros and three of them summed to 59.970000000000006. Every error was {"error": "something went wrong"}, so the web client string-matched the ones it could and showed the rest to the buyer. And the organizer's order list used ?page=400, which on a table gaining fifty rows a minute returned the last order of one page as the first order of the next, and the support ticket said the export was missing orders that were in the database the whole time.
This chapter redesigns the surface, and every URL, shape and error it names is the one the rest of the book uses. Resources replace actions, and the UUID replaces the sequence in every order URL. Shapes get one rule each: one timestamp format, integer cents, a PATCH that can tell absent from null, enums that grow and never shrink. The boundary parses bytes into typed values exactly once, and nothing inside re-checks them. Errors take one shape, RFC 9457, and each one is decided on what it reveals. Lists page by cursor, sort only by what an index can serve, and never count what they do not need to. Changes are additive until they cannot be, and then they expand, deprecate with a date, and contract. The last topic sets REST beside gRPC and GraphQL and says plainly which caller each one is for.
None of the three wounds from Chapter 1 closes here. The chapter builds the edge that the repairs will run through: POST /orders is the endpoint Chapter 7 gives an idempotency key, GET /events/{id}/seats is the one Chapter 9 puts in Redis, and the 404 that hides another buyer's order is the decision Chapter 5 enforces. An API designed once, properly, is why the later chapters can talk about mechanics without arguing about paths.