api-design

  • An API that had two clients and three shapes

    One endpoint, two consumers, and a response that differs by header. Three serialisation paths for one resource, two of them accidental.

  • An error response that told an attacker which field was wrong

    A login endpoint returning “unknown email” and “incorrect password” as separate messages, which is an account enumeration oracle with good intentions. Fixing the message and leaving the timing…

  • A 404 that should have been a 403, and the leak it caused

    An endpoint returning 404 for a resource that exists but belongs to somebody else, and 403 for one that exists and is forbidden — which distinguishes the two.…

  • Contract tests owned by the consumer, not by us

    Our tests asserting what our API returns, which proves nothing about what a consumer depends on. Owning the tests ourselves means asserting what we intended, and the whole…

  • The service we merged back

    Two services extracted in 2021, a team of four maintaining four pipelines, and forty-one of forty-four releases touching both.

  • Percentiles per consumer, not per endpoint

    An endpoint with a healthy p95 and one consumer for whom it was consistently slow. Aggregating across consumers averages away exactly the case that generates support tickets, and…

  • Rate limiting per key rather than per address

    A limit keyed on the client address, and four integrators behind one corporate gateway sharing a quota. Keying on the credential is the only fair unit when consumers…

  • A sparse fieldset that was invented by accident

    A response that omits fields when a header is present, implemented three years ago for one consumer and never documented. The behaviour was correct and the mechanism was…

  • json_validate on a webhook body before anything else

    A webhook endpoint accepting bodies up to eight megabytes, and the signature check running after the decode. Validating before decoding costs one pass over the string and allocates…

  • Include parameters, and the query language they become

    An include parameter added for one consumer, and eleven values later it is a query language with no grammar. An include parameter is a small query language and…