{"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"beat-the-invisible-man-unforced-errors-in-api-design","__idx":0},"children":["Beat the Invisible Man: Unforced errors in API design"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["I recently played a tennis match against someone vastly better than me."," ","He regularly beats players with active ATP points, so the outcome wasn't surprising."," ","He won easily."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["What surprised me came later, when I was alone on the court."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["While waiting for my daughter to finish a clinic, I started practicing serves by myself and invented a simple game:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If my first serve went in, I drop-fed a ball and hit a routine forehand."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If the serve was out, I lost the point."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If the forehand was out, I lost the point."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Otherwise, normal scoring."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["No opponent. No pressure. No tactics."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["And I couldn't dominate."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["I didn't lose badly — but I also didn't win comfortably. I couldn't beat the invisible man the way I felt I should."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["That's when it clicked: this had nothing to do with tennis."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-invisible-man","__idx":1},"children":["The invisible man"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The invisible man never:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["changes strategy"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["pressures you"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["exploits weaknesses"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every lost point is self-inflicted."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you can't win convincingly under zero pressure, pressure will only make things worse. Real opponents don't create problems — they expose them."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["That same pattern shows up all the time in APIs and technical documentation."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Most APIs don't fail because a competitor outplayed them."," ","They fail because of unforced errors."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"unforced-errors-in-apis-and-docs","__idx":2},"children":["Unforced errors in APIs and docs"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In tennis, an unforced error is a missed shot you should make. No one forced it. You donated the point."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In API design and documentation, unforced errors look like this:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["an endpoint that behaves differently than described"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["a parameter marked optional that's actually required"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["error responses that aren't documented or actionable"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["examples that don't compile, don't run, or don't match reality"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["concepts explained, but not when or why to use them"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["None of these require a competitor."," ","None require scale."," ","None require bad actors."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["They fail on their own."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["And often, you never hear about them."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-developers-you-never-see","__idx":3},"children":["The developers you never see"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The invisible man in APIs isn't hypothetical. It's very real:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the developer who gives up before making the first call"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the integration that never ships"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the trial that quietly expires"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the customer who churns without opening a ticket"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["They don't complain."," ","They don't escalate."," ","They don't show up in support metrics."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["They just… disappear."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When that happens, it's tempting to assume:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the product wasn't a fit"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the developer wasn't serious"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the problem was external"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["But often, it's just an unforced error."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-invisible-man-test","__idx":4},"children":["The invisible man test"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a simple test I've started using:"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If a careful, motivated developer followed your docs exactly —"," ","would they succeed without asking a question?"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["No Slack."," ","No support."," ","No tribal knowledge."," ","No retries."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Just the docs, the spec, and reality."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the honest answer is \"maybe,\" that's a problem."," ","Not a big, dramatic one — but a fundamental one."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["That's the equivalent of missing a routine forehand."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"why-pressure-makes-this-worse","__idx":5},"children":["Why pressure makes this worse"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["One reason these issues are easy to dismiss is that they don't always fail loudly."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In calm conditions, experienced developers compensate:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["they guess"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["they experiment"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["they reverse-engineer behavior"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["But pressure changes everything."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Under deadlines:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["ambiguity becomes risk"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In production:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["undocumented behavior becomes an incident"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["At scale:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["small inconsistencies multiply"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If your API only works when a developer is patient, experienced, and forgiving, it's not robust. It's fragile."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Just like tennis: if you can't win without pressure, pressure will expose you."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"beating-the-invisible-man","__idx":6},"children":["Beating the invisible man"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The goal isn't brilliance. It's reliability."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Some practical ways to reduce unforced errors:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["treat documentation as part of the API surface, not an afterthought"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["optimize for \"first successful call,\" not total feature count"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["make examples executable and kept in lockstep with reality"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["remove decisions instead of explaining them"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["document failure modes as carefully as success paths"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This isn't glamorous work."," ","It doesn't show up in launch posts."," ","But it compounds."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every unforced error you remove is a point you stop giving away."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"a-different-definition-of-quality","__idx":7},"children":["A different definition of quality"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["We often talk about API quality in terms of:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["expressiveness"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["flexibility"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["power"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Those matter — but they come later."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A more basic question comes first:"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Does this work exactly as described, without surprises?"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["That's how you beat the invisible man."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Not by adding more features."," ","Not by writing longer docs."," ","But by eliminating the small, silent failures that shouldn't exist in the first place."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"closing-thought","__idx":8},"children":["Closing thought"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Great APIs don't win because they're impressive."," ","They win because they don't give points away."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before worrying about competitors, scale, or advanced use cases, make sure you can beat the invisible man."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Everything else builds on that."]}]},"frontmatter":{"template":"../@theme/templates/BlogPost","title":"Beat the Invisible Man: Unforced errors in API design","description":"Most APIs don't fail because competitors outplayed them. They fail because of unforced errors—small mistakes that shouldn't exist. Here's how to identify and eliminate them.","seo":{"title":"Beat the Invisible Man: Unforced errors in API design | Redocly","description":"Learn how to identify and eliminate unforced errors in API design and documentation that cause silent failures and developer frustration.","image":"/content-assets/invisible-man-4186417b00e35003.png"},"author":"adam-altman","publishedDate":"2026-01-29T00:00:00.000Z","categories":["api-lifecycle:design","technical-documentation:writing-style","api-governance:compliance-quality"],"image":"invisible-man.png"},"tagList":[],"title":"Beat the Invisible Man: Unforced errors in API design | Redocly","lastModified":"2026-01-30T02:23:02.000Z"}