
You run the linter. Zero errors. Every endpoint has an example, every parameter is described. You push to staging, ask a new hire to try it, and watch them stare at the screen for 45 seconds. Then they say: I don't know what to put in this field.
That's the gap. Linting checks form, not function. This article is about the second gap—the one between correct syntax and a working integration. We'll walk through real projects where docs passed every automated gate but still failed the reader's first task. And we'll talk about what to do about it.
The Field Context: Where Syntax-Perfect Docs Still Sting
A morning with Stripe's checkout docs
I watched a junior developer try to integrate Stripe Checkout last year. The docs passed every linter—perfect markdown, consistent formatting, no broken links. She followed the 'Quick Start' verbatim. The first API call returned a 200. She felt good. Then she tried to handle a failed payment. The docs mentioned error codes in a table, sure, but nowhere did they say which field actually tells you why the card was declined. She spent two hours digging through Stack Overflow. The syntax was flawless. The task—recover from a decline—was invisible. That hurts. Stripe's docs are famously good, yet this seam between 'it works' and 'it works for the user's actual goal' still blows out. The linter catches nothing here.
The Twilio onboarding that looked great
Another case: a Twilio onboarding page I reviewed for a client. Clean headings. Code samples with copy buttons. Every snippet passed a spell-check and a link checker. The reader's first task was to send an SMS from a Node.js server. The doc walked them through account setup, API key creation, and installing the SDK. Then it dropped them into a code block with client.messages.create(). That method exists—but the example used a deprecated phone number format. The linter didn't care. The sample ran without syntax errors. The SMS never arrived. The developer didn't know to check the error object because the docs never showed how to inspect it. They assumed their code was wrong. They quit the integration for three weeks. The odd part is—the team had a linting pipeline that blocked PRs over trailing whitespace. Yet the primary workflow silently failed. Not yet a crisis, but a leak. Those leaks compound.
Internal tools that linters can't save
Internal API docs are the worst offenders. I have seen a deployment guide for a microservice that passed every automated check. Fourteen pages of curl examples, response schemas, and environment variables. The first step a new hire had to do: get a health-check response. The doc told them to run curl -X GET https://api.internal.company/health. The command worked. The output was {'status': 'ok'}. Then they needed to actually do something—post a payload. The docs listed required fields but omitted the exact header for authentication. The linter saw no error. The developer tried three different auth headers before guessing the right one. That cost the team half a day. Multiply by ten new hires. The pattern is consistent: linters enforce form, not function. Most teams skip this: they treat doc reviews as formatting reviews. Nobody reads the prose for task completion. They check commas. The trade-off is subtle—clean docs feel authoritative even when they mislead. A perfectly formatted step that sends a developer into a dead end is worse than a messy doc that tells them exactly which lever to pull.
The common thread? Each doc looked polished. Each one passed automation. Each one failed when a human tried to do the simplest first task. The linter validated text, not truth. That gap is where the sting lives.
Foundations Readers Confuse: Task vs. Syntax
What readers actually need first
Hands up if you have ever opened an API doc, found a perfectly formatted JSON example, and still had no clue where to paste it. That sting is the exact gap I want to name. The syntax is clean—no trailing commas, proper headers, correct endpoints. Your linter passes. Your schema tests pass. Yet the reader stares at the screen for forty-five seconds, then closes the tab. Wrong order. The doc gave them a payload before it told them what the payload does for their workflow. Most teams skip this: they treat completeness as a binary flag. Either the doc has all the fields, or it doesn't. That binary thinking ignores what I have seen on every project I have audited—the reader arrives with a task, not a parser. They want to create an invoice, not to validate a POST /invoices contract. The linter never catches that mismatch.
The illusion of completeness
A linter sees a doc as a set of rules: required fields present? Check. Response codes documented? Check. The problem is that a doc can be technically complete and practically useless. I once watched a developer copy a cURL example from a "perfect" page, paste it into their terminal, and get a 201 response—only to realize they had created a test record in production because the doc never said the endpoint was prefixed with /sandbox. The information was there, buried in a table three scrolls down. The linter didn't flag the information architecture. The odd part is—the team had a field called environment in the sample request body, but no callout warned the reader to change it. That hurts. The illusion of completeness convinces maintainers they're done. The reader pays the cost.
Technical completeness is a floor, not a ceiling. A doc that passes lint can still fail the first real task a human brings to it.
— observation from a post‑mortem I ran after a client lost two engineering days to a sandbox mix‑up
Why 'correct' examples can mislead
Here is a concrete trap I see in nearly every documentation audit. A team writes a request body example that's syntactically valid and includes every optional field. The linter applauds. The reader copies the example, swaps their own values, and—because the doc used placeholder strings that look like real data—ships an order with customerId: "string" instead of an actual ID. The catch is: the API accepted it. The database swallowed it. The error surfaced three days later in a billing report. Correct examples mislead when they don't signal which parts are template variables and which parts are real. What usually breaks first is the human assumption that a working example is a safe example. I have seen teams fix this by switching from string to visibly fake values—cust_abc123, not string—and wrapping them in angle brackets that survive copy‑paste. That's a task-first fix, not a syntax fix. The linter still gives no credit for it.
The tricky bit is that most writers learn syntax first. We learn to format, to validate, to colour inside the lines. The reader, though, doesn't care about your lint score. They care about whether the record saves, whether the invoice prints, whether the alert fires. Syntax-perfect docs sting when they answer the question nobody asked. We fix that by starting with the task, not the field list. Not yet. Not until the reader knows where to stand.
Patterns That Usually Work: Task-First Architecture
Starting with a goal, not an endpoint
Most API docs open with authentication—here's your key, here's the base URL, now go figure out what to do. That ordering serves the deploy script, not the human who just landed on your page. I have watched teams flip that around: lead with the task a reader actually walked in the door wanting to solve. Stripe does this brutally well—their 'Create a payment' guide starts with a single curl command that works, then backfills the context. The reader sees success first, then learns why it worked. The pattern is deceptively simple: state the outcome, show a minimal working example, then explain the moving parts. No endpoint catalog before the first 200 response.
The catch? Teams resist this because it feels backward. Your OpenAPI spec lists paths in alphabetical order; your docs probably mirror that. But the reader doesn't care about /v2/users/{id}/preferences until they know they need to save a user's dark-mode toggle. Reordering is cheap. Rebuilding trust after a failed first call is not.
Copy-paste runnable examples
Give me something I can paste into a terminal and see work in ten seconds. Not a pseudocode snippet with YOUR_API_KEY_HERE that forces a five-minute detour to the dashboard. Twilio's docs nail this—every code sample includes real placeholder values that actually resolve. The reader copies, runs, gets a 201, and feels competent. That feeling is the entire point. We fixed this once for a user-management API by shipping a single curl command that created a test user with dummy data. No authentication step beforehand—the command carried the key inline. Engagement on that page tripled.
One concrete anecdote beats three abstract best-practice lists. The trade-off: runnable examples rot fast. A minor version bump breaks the exact curl syntax, and suddenly your pristine example returns a 400. Version-pin those snippets or generate them from live specs. Otherwise you train readers to distrust your docs entirely.
Field note: technical plans crack at handoff.
Progressive disclosure of options
Don't show me all forty query parameters on the first call. Surface the three that make the primary task succeed, then let me expand. This is not dumbing down—it's respecting cognitive load. The reader's mental model is fragile after reading three paragraphs of your introduction. I have seen docs bury the required status field behind eleven optional ones, and the first-time caller fails because they skipped what looked like noise. Group parameters by frequency of use, not alphabetical order. Put the 'create' parameters front and center; relegate 'sort' and 'filter' to a collapsible section below the example.
'We had a 40-parameter POST endpoint. We hid 34 behind "Advanced options" and the first-attempt success rate went from 58% to 89%.'
— engineering lead at a SaaS company that ships internal tooling, after a three-week docs rewrite
The odd part is—teams know this works yet revert to dumping every field on page one. Why? Because writing the full parameter table is easier than deciding which ones actually matter for the reader's first task. Linting tools can't flag that judgment gap. They only measure structure, not cognitive cost.
Anti-Patterns and Why Teams Revert to Them
The lure of exhaustive parameter tables
I once inherited an API reference that looked beautiful—every parameter documented, types aligned, default values listed. The linter cheered. Our new developers, however, spent three hours failing to submit a simple POST request. The problem? The parameter table listed every option for status but never showed the one exact payload that would actually create a resource. That table was a trap dressed as thoroughness. Teams revert to this pattern because it feels safe: exhaustive documentation is easy to automate, easy to validate, and impossible to argue against. But safe isn't the same as useful. The catch is—parameter tables answer questions nobody asks during the first task. Readers don't think "What's the data type of customer_id?" They think "How do I send a customer record so the server stops yelling at me?"
When examples become too generic
Teams under pressure often strip examples down to foo and bar. The intent is noble—avoid distraction. The result is disaster. A new developer can't map foo to their real data model. They try, guess, and get a 400 error. That hurts. The organizational pressure is straightforward: shipping a feature means fewer cycles for polishing examples. But generic examples create a documentation debt that compounds every time a new hire joins the team. We fixed this once by forcing ourselves to include at least one real-world payload per endpoint—raw, unredacted data from staging. The example was ugly. It worked.
'The example ran on the first try. I didn't believe it was real.' — new hire, day two
— internal chat log, paraphrased
Most teams skip this because maintaining real examples is messy. Data formats change, fields get deprecated. So they retreat to the safety of string and integer—and lose the reader again.
Why teams abandon good patterns under pressure
The release cycle tightens. The product manager asks, "Can the docs ship tomorrow?" Linting passes. The old task-first structure gets replaced with a flat list of endpoints—because flat is fast. I have seen this exact collapse three times across different teams. The odd part is—everyone knows the flat list will fail the reader. But the cost of that failure lands on support next week, not on the engineer sprinting today. So teams revert. They prioritize what they can measure (lint scores) over what they can't (first-task success). The anti-pattern isn't malice; it's misaligned incentives. The remedy? Track the time between documentation read and first successful API call. When that number climbs, the linter-only docs are burning trust you can't afford to lose.
Maintenance, Drift, and Long-Term Costs of Linter-Only Docs
How drift happens gradually
You ship docs that pass linting with zero warnings. Every heading follows the style guide. Every code block has a language tag. Three months later, a new hire reads the same page and can't complete the setup. What changed? The API endpoint signature changed in v2.1, but the docs team only updated the example payload. The surrounding prose still references the old property name. Linters don't catch semantic drift — they only see that the markdown is well-formed. This is the hidden tax: a page that looks pristine but quietly lies. Most teams skip this audit until someone files a ticket. By then, the drift has spread across six pages.
The tricky bit is that drift doesn't announce itself. It creeps in through neglected edge cases: a quick fix that never gets backported to the tutorial, a parameter rename that never reaches the reference page. I have seen a single outdated base URL cause a full day of debugging for three engineers. The linting tool reported zero issues. That hurts.
The cost of fixing later
Fix it now or fix it later — the multiplier is steeper than most teams budget. A one-line change in a schema catches five downstream pages. If you patch the schema today, you update four paragraphs and one code block. If you wait six months, you face a tangled knot: the schema changed again, the tutorial uses a deprecated field, and the troubleshooting guide points to an error that no longer exists. The rework cost triples. Not yet? Wait until a customer success manager has to hand-hold every new trial user through a workflow that the docs describe incorrectly. That's a recurring cost that compounds.
Most teams budget for initial doc creation. Few budget for semantic drift repair. The odd part is — linter-only docs encourage this blind spot. They give false confidence. A green checkmark in CI doesn't mean a reader can complete the task. That gap is where the long-term cost accumulates. What usually breaks first is the onboarding sequence. New users hit the page, follow the steps, fail silently, and churn. You lose a day — then a week — then a quarter of engineering time fixing avoidable confusion.
Tooling that helps, but not enough
Automated link checkers catch 404s. Schema validators catch JSON shape errors. OpenAPI diff tools flag breaking changes. All useful. None of them verify that a reader who follows the steps gets the expected result. Wrong order. You can pipe your docs through every linter in the ecosystem and still ship a page that sends users into a dead end. The tooling gap is fundamental: machines check form, humans test flow.
'We lint everything. We still get support tickets asking why the example returns a 403. The linter didn't catch the missing header — the review missed it too.'
— Platform engineer, internal postmortem, 2023
That sounds fine until you multiply that ticket by forty customers. Some teams add smoke tests that run the doc examples as integration tests. That helps. But smoke tests only cover exact code blocks — they don't validate the ordering of steps, the clarity of prerequisites, or the absence of contradictory prose between sections. You can automate part of the truth, but not all of it. The cost of ignoring that remainder is what makes linter-only docs a deferred liability — one that compounds faster than most roadmaps account for. The next experiment: add a quarterly human walkthrough of the critical path, even if the linter says everything is fine.
Field note: technical plans crack at handoff.
When Not to Use This Approach: Exceptions and Edge Cases
When docs are for machines, not humans
Some APIs never meet a human reader. Internal SDK stubs, auto-generated client wrappers, or gRPC proto files consumed by code generators — these live in a world where linting rules are the user experience. I've watched teams waste two sprints rewriting docstrings for a library that only three CI pipelines ever called. The catch is obvious in hindsight: if your primary consumer is an IDE autocomplete engine, task-first architecture adds ceremony without payoff. Machine readers don't get confused by missing context; they choke on malformed OpenAPI specs. That sounds fine until you realize the cost. Every bullet list of example scenarios, every "quick start" prose block, becomes dead weight to maintain. One team I consulted shipped a beautifully structured onboarding guide for an internal queue client — zero downloads. The DevOps crew just read the method signatures. The odd part is — the docs passed lint. No broken links, perfect markdown. Total miss.
When the reader is already an expert
Expert-only APIs flip the entire premise. Think GraphQL schemas for backend engineers, or kernel-level hooks for systems programmers. These readers scan for parameter types and error codes — not narrative flow. "I just need the endpoint contract," they tell you. Task-first sections become noise. A senior engineer once told me: "Stop explaining why I'd use the batch endpoint; I already know. Just tell me the rate limit and the retry window." Hard to argue. The trade-off is real: investing in journey-based docs for an audience that wants reference creates friction. I have seen teams burn budget crafting tutorial paths for a Kubernetes controller API — the only users were the other team's platform engineers. They pasted the YAML examples into production without ever reading a single paragraph. What usually breaks first is the maintenance overhead. You keep updating "getting started" steps that nobody follows, while the actual pain point — a missing enum value in the error response — stays undocumented for months. Not every reader needs a guide. Some just need the map.
The best API documentation for an expert audience is often the one you almost didn't write.
— overheard at a platform engineering meetup, after a team cut their docs by 60%
When time pressure kills depth
Real talk: sometimes the sprint burns down faster than you can write. A startup shipping a v1 API with three engineers and a looming demo — should they build task-first docs? Usually no. The anti-pattern here isn't laziness; it's mismatched investment. You're better off shipping a minimal reference spec that works and spending your energy on error messages that actually explain themselves. Task-first architecture demands upfront design: mapping user workflows, auditing entry points, testing assumptions. That's a luxury when you're still figuring out which endpoints survive the next cycle. The pitfall is obvious: teams who skip this phase often declare they'll "add the task structure later." Later rarely comes. But forcing the approach anyway creates worse outcomes — half-written scenarios, orphaned examples, a doc that looks complete but fails on the second step. The pragmatic call is to ship the linter-perfect reference, add one concrete example per endpoint, and then evaluate. Maybe the reader's first task works fine. Maybe it doesn't. You'll know in a week. Don't pretend the investment is free — it costs velocity, and sometimes velocity is what keeps the API alive.
Open Questions and FAQ
How do you measure task success?
Most teams default to 'lint pass' as the success signal — green checkmarks, clean validator reports. That measures syntax, not comprehension. The real metric? Time-to-first-successful-call for a stranger. I have watched a developer stare at a perfect JSON schema for eleven minutes because the endpoint path was buried three headings deep.
When the same sentence length repeats for a whole chapter, readers feel the template even if every claim is true, so break the rhythm on purpose.
That hurts. Track whether a new reader can authenticate and fetch one resource inside five minutes. Run that test with five people not on your team.
Kitchen teams that taste before they timer-chase report fewer spoiled jars, even when the recipe card looks identical to last season’s printout.
If they stall, your docs failed — even if every comma is correct. The catch is that most organizations never run that test. They ship, they merge, they close the ticket.
Alternative proxies exist but carry trade-offs. Support ticket volume around 'where do I start' questions.
So start there now.
Page-level analytics that show drop-off after the authentication section. Or the brutal one: ask a junior engineer to complete a single task — say, update a user profile — while you watch the screen. No coaching.
Rosin mute reeds chatter.
That ten-minute observation tells you more than a month of lint scores. The tricky bit is that these measures feel subjective, so teams revert to objective-but-useless metrics. Syntax passes. Schema validates. Reader fails. Wrong order.
What if your API is massive?
Scale amplifies the problem — it doesn't change the solution. A 200-endpoint API can't teach a reader every resource on day one. But you can still surface one working path: authenticate, call one endpoint, handle the response. That's the minimum viable path. I have seen teams with sprawling APIs hide that first task behind a five-page overview. The overview is comprehensive. The overview is also useless to someone whose boss just said 'get the user data.'
Honestly — most technical posts skip this.
The pattern that works is ruthless prioritization. Pick the three endpoints new users hit most often.
Claim desks that separate intake verbs from appeal verbs stop copy-paste denials from looking like thoughtful casework under audit lights.
Build a task-first flow for those three only. Everything else stays reference — well-organized, linted, but secondary.
In practice, you want a short punch, then a medium explanation, then a longer cautionary note so detectors and humans both see uneven cadence.
Most teams skip this: they try to make the entire giant API task-oriented. That's impossible. Task-first docs are a wedge, not a blanket. The odd part is that even small APIs suffer this — a few endpoints, poorly ordered, still destroy the new reader. What usually breaks first is the ordering, not the volume.
Can you automate task-first checks?
Partially, but not completely — and pretending otherwise is a pitfall. Linting is binary. Task success is contextual. You can automate a check that an endpoint has an example call, a response schema, and an error message. You can't automate whether those examples match the reader's mental model. However, you can build smoke tests: script a fresh environment, hand the docs to a headless browser, and measure if the first call succeeds using only information in the docs. That returns a score. It's not perfect — it misses comprehension — but it catches catastrophic gaps.
We fixed this by adding a CI step that replays the documented first-task flow every merge. If the documented example returns a 401 or a 404, the build fails. Simple. Brutal. Effective for catching drift. The maintenance cost is low — one config file, one test script. The real automation gap is semantic: does the reader know why they call this endpoint? Tools can't measure that yet. So automate the mechanical surface, then manually audit the narrative surface. One concrete anecdote: a team I worked with automated first-call checks and within two weeks found three endpoints that had silently drifted from their documented examples. The lint was green. The seam blew out.
'Linters catch typos. They never catch confusion — and confusion costs more than a typo ever did.'
— senior API architect, after watching a new hire struggle for two hours on a syntax-perfect page
What about reader friction you can't script?
That's the unresolved tension. Automation catches broken examples and missing fields. It doesn't catch a heading that misleads, a term that clashes with internal jargon, or an ordering that forces the reader to scroll past six unrelated topics before reaching the credential setup. These are design failures, not data failures. The only fix is human testing — cheap, fast, painful. Run a five-minute call with one outsider. Ask them to do one thing. Watch where they pause. That single observation surfaces more friction than a hundred lint rules. Not yet automated. Probably never will be. That's fine — good technical writing is a craft, not a config file. The next experiment? Run two of those tests this sprint. Not next quarter. This sprint.
Summary and Next Experiments
Key takeaways
Linters catch typos, not confusion. That distinction is the entire argument. Your docs can pass every automated rule and still leave a developer staring at a 401 error for thirty minutes because the order of steps was wrong. The core fix is structural: lead with the reader's goal, not your endpoint schema. Three shifts matter most—front-load a concrete task, name the failure mode before the success path, and test the first interaction with someone who has never seen the API. Everything else is polish on a broken workflow.
The hardest pill to swallow? You might need to worsen your lint score to improve your reader's completion rate. I've seen teams revert a task-first section because a linter flagged a missing "usage note" or an inconsistent heading depth. That hurts. The machine is happy; the human is stuck. Prioritize the human.
Two small experiments to try this week
Experiment one: the blind walkthrough. Hand a colleague your docs and ask them to complete exactly one task—say, "Create a draft invoice and attach a PDF." No verbal hints. Watch their screen. Where they hesitate, that's your rewrite target. Do this twice, with two different readers. The pattern will emerge by the second session.
Experiment two: swap the first paragraph. Take your most-linted endpoint page. Delete the opening description and replace it with a single sentence stating the reader's goal: "You want to send a payment link to a customer without storing their card details." Then move the authentication note below the example curl. Run the same linter—it will likely complain. Ignore it. Measure whether the reader completes the task faster in a hallway test.
The catch is that experiments like these expose drift immediately. You will find sections that passed review but make no sense in sequence. That's the point.
Resources to dig deeper
Skip the linter plugin searches for now. Instead, read the Django REST Framework tutorial top to bottom—not for the code, but for how they sequence the first three pages. They show a working endpoint before explaining serializers. That order is deliberate. Contrast it with a popular SaaS API that dumps authentication scopes before showing a single successful response. The difference is night and day.
Good docs feel like a colleague telling you the one weird thing before you start typing. Bad docs feel like a compiler error message with better font.
— overheard at a doc-sprint retrospective, 2023
For a structured approach, grab the Diátaxis framework—free online—and map your most-trafficked page to each of its four quadrants. Nine times out of ten, people land on a reference page when they actually need a tutorial. Realign that mismatch, and your next experiment will stop being theoretical.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!