API Discoverability Myths You Should Ignore
Cover photo by Alina Grubnyak on Unsplash
Your API is not self-documenting. You hear folks say it all the time, usually claiming that if you name your resources well and follow REST patterns, developers will just figure it out. This is a myth. It sounds nice in theory, but in practice, it leads to endless Slack messages from confused coworkers.
Why the myth persists
We like to think that clean code is enough. If I structure my endpoints like /users/:id/posts, it feels logical. But logic for the author is often noise for the consumer. You’re building a system (a mental model) that another human has to reverse-engineer without a map. That’s hard.
When does self-discovery actually work?
It works only for the most trivial APIs. If you are building a CRUD wrapper over a single table, sure, maybe you don’t need a formal spec. But once you introduce side effects or complex state transitions, that logic falls apart. I’ve seen teams spend weeks fixing bugs because a consumer guessed the wrong request body format. It’s painful.
“But why can’t I just use HATEOAS?” you might ask. That’s a fair point. HATEOAS is elegant. The issue is that most HTTP clients don’t handle hypermedia links out of the box without extra plumbing. If you aren’t ready to invest in that tooling, HATEOAS is just extra bytes on the wire that nobody reads.
A practical approach to discovery
Don’t rely on the URL path to explain your API. Use OpenAPI specifications. Generate them from your code if you can. It gives developers a source of truth that tools like Postman or Insomnia can actually read. If you’re using TypeScript, try using libraries that derive your API contract directly from your types (tRPC is a great example of this, though it does lock you into a specific ecosystem).
// Example of defining a simple contractinterface GetUserParams { id: string; includePosts?: boolean;}
// Use this in your route handler to keep things predictableI admit, maintaining an OpenAPI spec can feel like chore work. It’s a drag to update a YAML file every time you change a field. If you hate manual docs, automation is your only path forward. If you don’t automate it, it’s already stale.
Are you prioritizing developer experience or just hoping your code looks intuitive enough to pass a quick review?