← All 73 books api design, one rule per page Get the full edition · £10
One rule per page

api design, one rule per page

Thirty rules for developers who ship endpoints but were never handed the contract underneath: the two envelopes every request and response really are, why safe and idempotent are the words that decide what crawlers and retries do to your data, POST as the honest escape hatch, PUT that replaces rather than merges, the five shelves of status codes from 401 asking for ID to 409 naming a conflict, redirects that keep the verb, Retry-After calming the stampede, and the OpenAPI file that turns one contract into docs, clients and mocks.


Steve Hodgkiss 5 rules

A diagram, the trap, and one thing to go fix this week. That's a page.

api design, one rule per page

Thirty rules for developers who ship endpoints but were never handed the contract underneath: the two envelopes every request and response really are, why safe and idempotent are the words that decide what crawlers and retries do to your data, POST as the honest escape hatch, PUT that replaces rather than merges, the five shelves of status codes from 401 asking for ID to 409 naming a conflict, redirects that keep the verb, Retry-After calming the stampede, and the OpenAPI file that turns one contract into docs, clients and mocks.


Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).

HTTP semantics checked against RFC 9110 (HTTP Semantics, June 2022) fetched from rfc-editor.org and read during this build; request-method guidance cross-checked against MDN Web Docs HTTP reference pages (developer.mozilla.org); OpenAPI facts checked against the official OpenAPI Specification 3.1.1 from the OpenAPI Initiative (spec.openapis.org). Status codes, headers, method properties and field names are quoted as those sources state them. Teaching conventions (one rule a page) are named as conventions. An independent guide, not affiliated with or endorsed by the IETF, Mozilla, or the OpenAPI Initiative.

General information only. Not professional advice; verify against the current specifications and your own stack.

© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.

Edition 1.0 · stevehodgkiss.net

Contents

Contents


Part 1 · The trade4
A request, a response5
Safe means read-only6
Idempotent survives7
Part 2 · Status codes8
The five shelves9
401 asks, 403 refuses10
Part 1 of 2
methods, semantics
1

The trade

What a request and a response actually are, and the method properties, safe and idempotent, that decide what the network, crawlers and retries are allowed to do to your data.


In this part
  1. 01A request, a response
  2. 02Safe means read-only
  3. 03Idempotent survives

Per RFC 9110 section 6: a request message includes a request line containing a method, a target URI, and the HTTP version; request messages can also contain header fields and content. Section 15: the status code of a response is a three-digit integer code that describes the result of the request.

api design · No. 01
The trade

A request, a response

The whole conversation

The whole conversation is two envelopesclientserverrequestGET /orders/42method + target + version, then headersresponseHTTP/1.1 200 OKa three-digit status, then headers, then contentRequest on top, response underneath. That's the entire protocol's shape.

Let's say you write endpoints all day and have never seen the shape underneath. A request is a method, a target, and the version, then headers, then optional content. That's all a client ever sends.

The server answers with a three-digit status code that, per RFC 9110, describes the result of the request, plus its own headers and content.

Two envelopes. Everything else in this book is about what you write on them.

TRY THIS WEEK

Open your browser's devtools network tab today and read one request line and one status line out loud.

Per RFC 9110 section 9.2.1 Safe Methods: request methods are considered safe if their defined semantics are essentially read-only; of the request methods defined by this specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. The purpose of the distinction is to allow spiders and prefetching to work without fear of causing harm.

api design · No. 02
The trade

Safe means read-only

GET, HEAD, OPTIONS

The safe zone is read-only to the coreGETHEADOPTIONSTRACEsafe: essentially read-only semanticsspiders and prefetchingmay follow every GETwithout fear of causing harmThe classic trap:GET /page?do=deletean unsafe action behind a safeverb gets crawled, prefetched,indexed, triggered.The safe list is a promise to every automated process on the web.

Let's say your delete link is a GET because it was easier to put in an href. Safe, per RFC 9110, means the defined semantics are essentially read-only: GET, HEAD, OPTIONS and TRACE.

The reason the word exists: safe methods let spiders and prefetching work without fear of causing harm. The spec calls out the page?do=delete pattern by name: automated processes will GET every URI for link maintenance and indexing, and the unfortunate side effect is yours.

Anything that changes state, a crawler will eventually trigger. Don't hand it a GET.

TRY THIS WEEK

Grep your routes for state changes reachable by GET this week. Each one is a bug waiting for a crawler.

Per RFC 9110 section 9.2.2 Idempotent Methods: a request method is considered idempotent if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. PUT, DELETE, and safe request methods are idempotent. Idempotent requests can be repeated automatically if a communication failure occurs before the client reads the response.

api design · No. 03
The trade

Idempotent survives

Retry the same, get the same

Send it three times, one state resultsclientconnection lostdid it land?PUTx3 identicalone stateclients may retryautomaticallyPOSTx3 identicalstatestatestateproxies MUST NOTauto-retry theseIdempotent: repeat the request, same intended effect as once.

Let's say the connection dies after you sent the request but before you read the response. For idempotent methods the question doesn't hurt: multiple identical requests have the same intended effect as one. PUT, DELETE, and the safe methods qualify.

So the client can repeat the request on a new connection. POST can't: RFC 9110 says a proxy MUST NOT automatically retry non-idempotent requests, since three identical POSTs may mean three orders.

The network will eat a request someday. Design so the retry is free.

TRY THIS WEEK

List your POST endpoints that a lost response would make dangerous. Those are your idempotency-key candidates.

Part 2 of 2
the five shelves
2

Status codes

The response's first digit is a contract. The codes that carry the most meaning per character: who erred, what conflicts, what moved, and what the client should do next.


In this part
  1. 01The five shelves
  2. 02401 asks, 403 refuses

Per RFC 9110 section 15: the status code of a response is a three-digit integer code; all valid codes are 100 to 599. 1xx informational, 2xx successful, 3xx redirection, 4xx client error, 5xx server error. A client MUST understand the class of any status code and treat an unrecognized code as the x00 code of that class; values outside 100..599 are invalid and SHOULD be processed as 5xx.

api design · No. 04
Status codes

The five shelves

The first digit rules

Five shelves, first digit decides1xxinformationalrequest received, continuing2xxsuccessfulreceived, understood, accepted3xxredirectionfurther action needed4xxclient errorthe request erred5xxserver errorthe server failed a valid requestMystery code?471400read it as the x00 of its classA client must understand the class of any code. The first digit is the contract.

Let's say your API invents status 437 and a client chokes. The spec already planned for that: a client must understand the class of any code and treat an unrecognized one as the x00 of its class. A mystery 471 reads as a 400.

The five shelves: 1xx the request was received, 2xx received, understood, accepted, 3xx further action needed, 4xx the client erred, 5xx the server failed a valid request.

The first digit is the contract. The last two are your vocabulary.

TRY THIS WEEK

Skim your API's response codes today and confirm every one sits on the shelf whose meaning it actually has.

Per RFC 9110 section 15.5.2: the 401 response MUST send a WWW-Authenticate header field containing at least one challenge. Section 15.5.4: 403 means the server understood the request but refuses to fulfill it; the client SHOULD NOT automatically repeat the request with the same credentials. MDN notes 401 semantically means unauthenticated.

api design · No. 05
Status codes

401 asks, 403 refuses

Who are you, versus no

Two doors, two different answers401who are you?unauthenticated.WWW-Authenticate: challengemust come with thechallenge: show credentials403no.understood, refused.identity known, stillnot enough. Don't resentthe same credentials.401 asks for ID at the door. 403 checked it and said no anyway.

Let's say your API answers 401 for every denial. The two codes split the question. 401 means unauthenticated: the server doesn't know who you are, and the response must carry a WWW-Authenticate challenge.

403 means the server understood and refuses: it knows you, and your credentials are not enough. The spec adds the discipline: the client should not repeat the request with the same credentials.

401 is a locked door asking for ID. 403 is ID checked, entry denied.

TRY THIS WEEK

Audit your auth middleware today: which denials are truly missing credentials, and which are 403s wearing 401?

Index

Index


401 asks, 403 refuses10
A request, a response5
Idempotent survives7
Safe means read-only6
The five shelves9