Listen Documentation Audit
One line: the prose docs are feature-rich and recently expanded, but the machine-readable layer is broken at the root — the published OpenAPI spec is an untouched vendor sample, the authentication rules contradict the endpoint examples, and prominently-marketed features link to 404s. An AI agent pointed at these docs would generate a client for the wrong API.
1. The published OpenAPI spec is the default Mintlify sample, not Listen's API (critical)
Location: /api-reference/openapi.json (listed under "OpenAPI Specs" in llms.txt)
Problem: The spec served at this path is the unmodified Mintlify "OpenAPI Plant Store" sample. Its info.title is "OpenAPI Plant Store", its only server is "http://sandbox.mintlify.com", its paths are /plants and /plants/{id}, and its security scheme is bearerAuth (HTTP bearer). None of this relates to Listen's real API, which lives at https://listenlabs.ai/api/public/..., authenticates with an x-api-key header, and exposes endpoints like /responses/{link_id}, /list_surveys, and /studies/{study_id}/questions.
Consequence: This is the single artifact AI coding agents and client generators are most likely to consume. Anyone running openapi-generator, importing into Postman, or letting an agent "discover the API" gets a fictional plant store pointed at a sandbox host with the wrong auth model. The generated client cannot make a single valid Listen API call, and the failure is silent — the spec is valid, just entirely wrong.
The fix: Replace the sample file with a real spec describing the /api/public/... endpoints, the x-api-key/x-id headers, and the actual listenlabs.ai server. Until then, remove it from llms.txt so agents don't treat it as canonical.
2. Auth page says the API key "only supports the /responses endpoints" — but two other endpoints authenticate with it (critical)
Location: /get-api-access (vs /endpoint, /get-study-questions)
Problem: The authentication page states: "Note that this method currently only supports the /responses endpoints." But the List Studies endpoint (GET /api/public/list_surveys) and Get Study Questions endpoint (GET /api/public/studies/{study_id}/questions) are not /responses endpoints, and both of their own curl examples authenticate with -H 'x-api-key: '. Reinforcing the conflict, /method-1 re-documents list_surveys under the same key-authenticated API, and the data map presents GET /studies/{study_id}/questions as part of it as well.
Consequence: A developer reads the auth restriction and concludes they cannot list their studies or fetch a study's questions with their API key — or, conversely, copies the List Studies example and can't tell whether a failure is "wrong auth method" or "the docs lied about scope." Either the restriction is stale or the examples are wrong; both can't be true, and an agent has no way to resolve it.
The fix: State precisely which endpoints the x-api-key method covers. If it now covers list_surveys and studies/{id}/questions, delete the /responses-only sentence; if it doesn't, remove x-api-key from those endpoints' examples and document the correct auth.
3. Two endpoint sets disagree about the same API — fields, defaults, and example values (significant)
Location: /method-1 (legacy combined reference) vs /get-responses, /get-single-response
Problem: The legacy /method-1 page re-documents Get Responses, Get Single Response, and List Studies and contradicts the dedicated pages:
- Field set:
/method-1's Get Responses lists onlyid,response_number,created_at,updated_at,answers,answers_array,attributes, andshort_transcript. The dedicated/get-responsespage additionally documents and returnsquality_score,tags,tagline,summary, andshort_assistant_messages(all present in its field list and example JSON), and the data map addsprogressandbullet_summary. None of those extra fields appear on/method-1. - Defaults:
/method-1showsper_page default:"1000"andinclude_in_progress default:"true";/get-responsesdescribes the same params in prose with no names or defaults at all. - Deprecated field value: In
/method-1, the deprecatedquestion_idexample is"q-001"/"q-002"; in/get-responsesthe deprecatedquestion_idequals theanswer_idUUID (f1e2d3c4-…0001)./get-single-responseuses yet a third deprecated field,question_uuid, absent from/method-1.
Consequence: A developer or agent that lands on /method-1 builds against a smaller, differently-shaped response and a different deprecation contract. Code written to migrate off question_id will do the wrong thing depending on which page it read, and parsers will miss summary/quality_score/tags entirely.
The fix: Delete or redirect /method-1 to the dedicated pages. One endpoint should have exactly one reference. Document page/per_page/updated_since/include_in_progress with names and defaults on /get-responses.
4. No error responses or status codes documented for any REST endpoint (significant)
Location: /endpoint, /get-responses, /get-single-response, /get-study-questions, /method-1
Problem: Every REST endpoint page documents only the 200 response body. No page lists status codes, error shapes, rate limits, or auth-failure behavior. (The sample OpenAPI spec defines an Error schema, but it's for the plant store, not Listen.)
Consequence: A developer can't program defensively — there's no documented signal for an invalid link_id, an expired/invalid x-api-key, a missing study, or throttling. Agents that need to branch on error conditions have nothing structured to parse, so they fail silently or retry blindly.
The fix: Add an "Errors" section with the real status codes and the JSON error body shape, plus any rate limits, for each endpoint (or in a shared reference page).
5. Path param named study_id actually requires a link_id (significant)
Location: /get-study-questions, /data-map
Problem: The Get Study Questions endpoint is GET /api/public/studies/{study_id}/questions, and its path parameter is described as "The unique ID of the study." But the example calls studies/my-study/questions (a link_id-style value), and the data map's join-keys table confirms: "study_id … Path param in GET /studies/{study_id}/questions. Uses the link_id value." Meanwhile List Studies returns both an immutable id (uuid) and an editable link_id.
Consequence: A developer naturally passes the study's id (uuid) into a slot literally named study_id and gets nothing back. Because link_id is editable in study settings ("might change"), callers who hardcode it will break later. The naming actively misleads.
The fix: Rename the param to link_id (or document loudly that study_id expects the link_id, not the uuid id), and note the mutability caveat.
6. Two separate, divergent "Authentication" pages, one ending in an empty broken link (significant)
Location: /get-api-access and /request-api
Problem: There are two authentication pages. /get-api-access documents Method 1 (x-api-key) and Method 2 (Google ID token). /request-api (titled "Authentication" / "Get API Access") duplicates only Method 1 and ends with a malformed Markdown heading whose link text is empty: ### [****](https://docs.listenlabs.ai/api-reference/authentication#method-2-google-id-token). That target points to /api-reference/authentication, a path that doesn't match the real auth slug (/get-api-access).
Consequence: Readers hit two overlapping auth pages and can't tell which is canonical; the one that gestures toward Method 2 does so via an empty, unlabeled link to a non-existent path, so the Google ID token method is effectively unreachable from /request-api.
The fix: Consolidate to a single authentication page and fix or remove the empty heading link.
7. The same recruitment surface is called both "Recruit tab" and "Launch tab" (significant)
Location: /get-started/studies-overview (FAQ) vs /setup-to-launch/recruiting-participants (Recruiting 101)
Problem: The FAQ repeatedly instructs users to "go to the Recruit tab" — "Go to Recruit tab → Share a Link," "Export complete responses in the Recruit tab." Recruiting 101 calls the identical surface the "Launch tab": "The Launch tab is your command center," "Click Launch at the top right of the Launch tab." There is no "Recruit tab" in Recruiting 101 and no "Launch tab" in the FAQ.
Consequence: A new user following the FAQ looks for a tab labeled "Recruit" that the primary recruiting guide calls "Launch," and can't reconcile the two. Step-by-step instructions ("Go to Recruit tab → Share a Link") become impossible to follow if the UI uses the other name.
The fix: Determine the actual tab label in the product and use it consistently across both pages.
8. Language-support count contradicts itself across the docs — and the canonical list backs none of the figures (significant)
Location: /get-started, /setup-to-launch/auto-translations, /setup-to-launch/multi-lingual-voice-interviewer, /setup-to-launch/languages-complete-list, /setup-to-launch/recruiting-participants
Problem: The number of supported languages changes by page, and several pages contradict themselves:
- get-started: Emotional Intelligence works "across 50+ languages"
- Auto-Translations: intro "90+ supported languages" but its own FAQ "translations across ~100 languages"
- Multilingual Voice: header "40+ languages," body "42 supported languages," and a note that Auto-Translations "covers ~100 languages"
- Recruiting 101: panel spans "100+ languages"
- Complete list page: "90+ languages," but the "All Supported Languages" table contains only ~86 distinct entries
Consequence: A buyer evaluating market coverage gets a different answer on every page and can't trust any of them; the one page that should be authoritative (the complete list) undercounts its own stated figure. For voice specifically, "40+" vs "42" vs the list page's totals can't all be reconciled.
The fix: Establish two canonical numbers — text/translation languages and voice languages — derived from the actual list, and reference those everywhere instead of restating ad-hoc counts. Make the complete-list table match the stated total.
9. Prominently-marketed "Mission Control" feature has no docs page and links to a 404 — twice (significant)
Location: /get-started ("How It Works" step 5 and Key Features), /insights-and-reports/personas
Problem: The get-started overview links "Mission Control" to /insights-and-reports/mission-control in two places, and the Research Agent page says it pulls from "your organization's full history in Mission Control." That slug returns HTTP 404 (page_not_found). No documentation page for Mission Control exists anywhere in the scraped docs.
Consequence: A reader who clicks the most-repeated cross-cutting feature in the product overview lands on a 404. Worse, Research Agent's core "across studies" capability is described as depending on a feature with zero documentation, so a developer can't learn what Mission Control actually is, how to enable it, or what data it spans.
The fix: Publish the Mission Control page at the linked slug, or repoint the links and remove the references until the page exists.
10. "Emotional Intelligence" feature links to the wrong (404) slug (significant)
Location: /get-started Key Features → /insights-and-reports/emotional-understanding
Problem: The Key Features list links "Emotional Intelligence" to /insights-and-reports/emotional-understanding, which returns 404. The actual page exists at /insights-and-reports/emotional-intelligence. The slug used in the link matches the alternate name the feature is also called in body copy ("Emotional Understanding analyzes behavioral signals…"), suggesting the feature was renamed without updating the link.
Consequence: The marketed link to a flagship analysis feature is dead on the primary entry page.
The fix: Repoint the link to /insights-and-reports/emotional-intelligence and standardize on one feature name (see issue 11).
11. Feature/page naming drift: "Emotional Intelligence" vs "Emotional Understanding," and a personas slug titled "Research Agent" (significant)
Location: /insights-and-reports/emotional-intelligence, /insights-and-reports/personas
Problem: The Emotional Intelligence page is titled and referenced as "Emotional Intelligence," but mid-page switches to "Emotional Understanding analyzes behavioral signals…" — and the get-started link used the emotional-understanding slug (which 404s). Its benchmark wording also drifts: the intro says the model is "benchmarked against MELD," while the body says it is "validated against academic benchmarks (CMU-MOSEI and MELD frameworks)" — MELD appears in both, but the body adds a second benchmark the intro omits. Separately, the page at slug /insights-and-reports/personas is titled "Research Agent" and the word "personas" never appears.
Consequence: Search, support, and agents can't reliably map a name to a feature when one feature has two names and one URL describes a different feature than its slug. And a reader can't tell whether the accuracy claim rests on MELD alone or on MELD plus CMU-MOSEI, because the two passages don't state the same benchmark set.
The fix: Pick one feature name and use it in title, body, and link slug; state one consistent benchmark set in both the intro and body; fix the personas slug to match its "Research Agent" content (or redirect).
12. Quality Guard is described with two non-overlapping definitions (significant)
Location: /get-started (Key Features) vs /setup-to-launch/fraud-prevention-and-quality-guard
Problem: get-started says Quality Guard analyzes "voice patterns, response depth, tab-switching, copy-paste, contradictions, and repeat respondents." The dedicated Quality Guard page says every response is scored across five named dimensions: "Informativeness, Response depth, Engagement, Follow-up quality, Repetitiveness." Only "response depth" overlaps. The dedicated page also introduces "Listen Atlas — Listen's AI orchestration layer," a named product that appears nowhere else in the docs.
Consequence: A buyer or developer can't tell what the quality score actually measures, because the two descriptions barely intersect. "Listen Atlas" is presented as a real component with no definition or page, so its role in participant verification is undocumented.
The fix: Reconcile the two Quality Guard descriptions into one signal list (detection signals vs scoring dimensions, clearly separated), and either document "Listen Atlas" or stop naming it as a distinct feature.
13. Get Single Response example data is internally inconsistent (minor)
Location: /get-single-response
Problem: The data map says the survey field equals the study's link_id. The example curl requests responses/study-1/... (link_id study-1), but the returned object has "survey": "audio-survey". The two values don't match within the same example.
Consequence: A developer using the example to learn the join model sees survey ≠ the link_id they requested, contradicting the documented join key and casting doubt on how to correlate single responses back to a study.
The fix: Make the example self-consistent — the returned survey should equal the link_id used in the request URL.
14. Data map omits fields the endpoints actually return (minor)
Location: /data-map (Response and Answer entities)
Problem: The data map is presented as the entity reference, but its Response table omits summary, short_assistant_messages, and the deprecated question_id/question_uuid fields that /get-responses and /get-single-response document and return.
Consequence: A developer who treats the data map as the schema source of truth will not allocate for fields that arrive in the payload, and won't see the deprecation guidance that's only on the endpoint pages.
The fix: Sync the data map to the full field set the endpoints return, including deprecated fields with their replacement notes.
15. FAQ question "How many languages does Listen support?" has no answer (minor)
Location: /get-started/studies-overview (Languages & Localization)
Problem: The bolded question "How many languages does Listen support?" is immediately followed by the next bolded question ("Can I see what the translated guide looks like?") with no answer text in between. The count only appears, in passing, inside the answer to the next question ("90+ languages, and 40+ languages with voice moderation").
Consequence: The most direct language question in the FAQ renders blank, and the figure it should contain is one of several conflicting counts (see issue 8).
The fix: Add the answer directly under the question, using the canonical counts.
16. Internal Slack link and a malformed relative link shipped in public docs (minor)
Location: /setup-to-launch/auto-translations, /setup-to-launch/multi-lingual-voice-interviewer
Problem: On Auto-Translations, the "+ Add Translations" UI step links to https://listen-labs.slack.com/archives/C070U1WMZEY/p1773256279931529 — an internal Slack workspace URL embedded as the link target. On the Multilingual Voice page, the link to Auto-Translations is written as [...](setup-to-launch/auto-translations) with no leading slash, so it resolves to /setup-to-launch/setup-to-launch/auto-translations (404).
Consequence: A reader clicking "+ Add Translations" is sent to a private Slack workspace they can't access; a reader following the voice→translations cross-link hits a 404.
The fix: Remove the Slack URL (it looks like an editorial paste error) and point the step at the right docs/UI; add the leading slash to the relative link.
17. MCP tool/field names are referenced but never documented in a tool reference (minor)
Location: /mcp-docs/connect, /mcp-docs/troubleshooting
Problem: The MCP pages reference tools list_studies and get_study_analysis and a has_analysis: true field as if they're documented elsewhere ("Check list_studies for has_analysis: true"), but no MCP tool-reference page exists in the docs. The troubleshooting section also renders error conditions as bare lines detached from their headings, so symptom→fix mapping is hard to follow.
Consequence: A developer can't see the full list of MCP tools, their arguments, or their return shapes — only the few names that happen to appear in prose. The REST API similarly has no OAuth/refresh-token equivalent, so the two surfaces (MCP OAuth 2.1 vs REST x-api-key) are documented at very different depths.
The fix: Add an MCP tool-reference page listing each tool, its parameters, and its output fields (including has_analysis), and restructure troubleshooting so each error maps clearly to its resolution.
18. Typos in load-bearing API and UI docs, including in field descriptions (minor)
Location: /endpoint, /get-responses, /get-started, /insights-and-reports/emotional-intelligence, /setup-to-launch/auto-translations, /get-started/studies-overview
Problem: Spelling/grammar errors recur in text that gets read and copied: "lists all studys" / "Returns a list of studys" (the List Studies endpoint), "responses that who's analysis is still in progress" (query-param description, repeated on /endpoint and /get-responses), "Suprise" (in the list of Ekman's six emotions), "Configure Your Study Lanaguage," "read-only acess," and on get-started the broken phrasing "find and qualifies participants."
Consequence: Individually cosmetic, but several sit in field descriptions and feature lists where they reduce confidence in technical accuracy, and "studys" appears in user-facing endpoint copy that gets copied into client code comments.
The fix: Run a spell/grammar pass across the API reference and setup pages; prioritize the field-description and endpoint-summary strings.
What they do well
- The MCP integration docs (
/mcp-docs/connect) are genuinely well-structured: explicit server URLs, OAuth 2.1 flow, token lifetimes in a table, per-permission scope list, and cleanup behavior — a model for how the REST auth pages should look. - The data map's join-keys table is a strong idea — explicitly documenting
Study→Response→Question→Answer→TranscriptRowrelationships is exactly what agents need to correlate entities (it just needs to be complete and consistent with the endpoints). - Enterprise security claims (SOC 2 Type II, ISO 42001/27001/27701, 256-bit encryption, no-training-on-data) are stated specifically enough to be verifiable, rather than vague assurances.
Top 3 recommendations
- Replace the OpenAPI spec. Ship a real spec for the
/api/public/...endpoints with correct host andx-api-key/x-idauth, and remove the plant-store sample from llms.txt. This is the highest-leverage fix for both agents and client generators. - Make authentication self-consistent. Reconcile the "
/responses-only" claim with the endpoints that authenticate viax-api-key, consolidate the two auth pages into one, and add error/status-code documentation to every REST endpoint. - Pick one name for everything and dedupe pages. One language count (text vs voice), one tab name (Recruit vs Launch), one feature name (Emotional Intelligence vs Understanding), and one reference per endpoint — delete
/method-1and the duplicate auth page, and fix the Mission Control / Emotional Intelligence 404 links.