Coveo Documentation Audit
The docs are broad, well-organized, and explicitly court AI agents with a site-wide "append .md" banner and an llms-full.txt index — but that agent-facing export is where the platform breaks: it strips placeholders out of code templates (collapsing both headers and URL paths), 404s on the Swagger-backed reference pages that prose links via .md (verified on the Search and Index API references), and renders the deprecations hub as raw template code. Layered on top are three competing endpoint conventions, three token types with three lifetimes, and a misspelled field in a response example.
1. The .md "AI agent context" export strips every <placeholder> — blanking headers and collapsing URL paths (critical)
Location: https://docs.coveo.com/en/114.md (Perform a simple query) and https://docs.coveo.com/en/p3ob0090.md (Answer API)
Problem: Every page carries the banner "A markdown version of this page is also available by appending .md to this page URL." But the .md export deletes all <angle-bracket> placeholders. On /en/114.md the request template becomes POST https://.org.coveo.com/rest/search/v2?organizationId= with Authorization: Bearer and a payload of { "q": }, while the live HTML correctly shows https://<MyOrganizationId>.org.coveo.com/..., Authorization: Bearer <MyAccessToken>, and { "q": <MyQuery> }. The "Replace `` with…" legend also loses its inline-code targets, so the instructions reference nothing. The Answer API page (/en/p3ob0090.md) shows a second, independent failure mode: the stripped placeholders collapse the URL path itself into empty segments — POST https://.org.coveo.com/rest/organizations//answer/v1/configs//generate (missing org host segment, organizations//, and configs//generate) — plus an empty endpoint and an empty "Where:" legend.
Consequence: An AI coding agent — the exact consumer this .md export is built for — extracts a request body that is invalid JSON ({ "q": }), an endpoint with a missing hostname segment, a Bearer header with no token, and (on the Answer API) a request path with collapsed // segments that can't be repaired by guessing. The instructions telling it what to substitute are also blanked out, so it can't self-correct. This silently breaks the primary copy-paste path for the audience the feature targets.
The fix: Escape or HTML-encode angle-bracket placeholders when generating the .md source (e.g. backtick-wrap them or emit <MyAccessToken>) so the markdown export preserves <MyOrganizationId>, <MyAccessToken>, <MyQuery>, and path-segment placeholders exactly as the rendered HTML does. Add a regression check that diffs placeholder counts (and flags collapsed // path segments) between HTML and .md.
2. .md links to Swagger/OpenAPI reference pages 404 — verified on the Search and Index API references (critical)
Location: https://docs.coveo.com/en/13.md (Search API reference) and https://docs.coveo.com/en/9.md (Index API reference)
Problem: Verified HTTP HEAD checks (2026-06-09, via headless Chromium against docs.coveo.com / CloudFront) return 404 for https://docs.coveo.com/en/13.md and https://docs.coveo.com/en/9.md, while /en/143.md returns 200 text/markdown. Yet prose across the docs links the Search API reference using .md with deep anchors: the error-codes page (/en/1471) links "the Search API (https://docs.coveo.com/en/13.md)" and "numberOfResults parameter (https://docs.coveo.com/en/13.md#operation/searchUsingPost-numberOfResults)", and the version-differences page (/en/p7lg0496) links "https://docs.coveo.com/en/13.md#tag/Search-V2/..." and "https://docs.coveo.com/en/13.md#tag/Search-V3/operation/fieldsV3". All resolve to 404. Only slugs 13 and 9 were tested; both are Swagger/OpenAPI-backed reference pages, and the "Reference" subgroup in llms-full.txt consistently links such pages with trailing-slash URLs (/en/9/, /en/5/, /en/6/) rather than .md, which suggests the missing-.md behavior is systemic to OpenAPI-backed slugs — but that broader claim is inferred, not exhaustively verified.
Consequence: The site-wide banner promises a .md version "by appending .md to this page URL," but for at least the Search and Index API references that promise is false. Every cross-reference into those references from .md consumers is a dead link — an agent following the error-codes page to look up a parameter hits a 404 instead of the reference.
The fix: Either generate real .md exports for the Swagger-backed reference slugs, or rewrite the in-prose links to point at the trailing-slash page URLs (/en/13/, /en/9/) that actually resolve — and make the banner conditional so it doesn't advertise a .md variant on pages that lack one. While you're in there, sweep the remaining OpenAPI-backed slugs (e.g. /en/3430, /en/5, /en/6, /en/103) to confirm the scope.
3. The Deprecations hub page renders unprocessed Liquid template code in .md — zero actual notices (critical)
Location: https://docs.coveo.com/en/q2ib0310.md (Deprecations and end of support)
Problem: This page is described as the place that "lists all active deprecation and end-of-support notices." In the .md export, the entire notices table is unrendered Jekyll/Liquid template source: {% assign by_order = site.deprecations | where_exp: ... %} followed by a single template row | {{ notice.deprecation-date }} | [{{ notice.title }}]({{ site.baseurl }}/{{ notice.slug }}/) |. None of the loop variables are populated, so the agent-facing version of this critical page contains no real deprecation dates or titles, even though the underlying notices (e.g. ".NET (C#) Platform SDK", "Search and listing configuration APIs deprecation") exist as separate pages.
Consequence: An agent or .md reader consulting the canonical deprecation hub sees an empty templated table and concludes there are no active deprecations — the opposite of the truth. Migration planning that relies on this page silently misses every end-of-support date.
The fix: Render the Liquid {% for %} loop server-side before producing the .md export so the table contains the actual notice rows, or have the .md generator follow the same data source the HTML uses to populate site.deprecations.
4. Misspelled field name permantentid in the Search API response example (significant)
Location: https://docs.coveo.com/en/1445.md (Perform a query), 200 OK response body excerpt
Problem: The sample response lists "permantentid": "ecc3fac2..." inside raw. The correct Coveo field is permanentid, so the copy-paste example ships a misspelled core result field. The same response example is also flagged in the source for a likely typo in a comment field name — meaning the typo is not an isolated one-off in this excerpt.
Consequence: A developer or agent that keys off the example — e.g. result.raw.permantentid — reads undefined at runtime, because the actual field is permanentid. Because the example is the only concrete shape of the response a reader sees, the typo propagates straight into client code.
The fix: Correct permantentid to permanentid in the /en/1445 response example, fix the flagged comment-field typo on the same page, and grep the docs corpus for both so the cleanup doesn't stop at the first hit.
5. Error contract is explicitly inconsistent — errorCode "may not appear" (significant)
Location: https://docs.coveo.com/en/1471.md (Troubleshoot query error codes)
Problem: The page warns that "the errorCode field is optional and may not appear in all error responses," and the examples bear this out: the entire 400 BAD_REQUEST family returns only { "statusCode", "message" } with no errorCode (e.g. { "statusCode": 400, "message": "Invalid JSON format in request body." }), while NO_REGISTERED_ENDPOINT, QUERY_PIPELINE_INTERRUPTED, and 401 UNAUTHORIZED do include errorCode. There is no documented rule for which errors carry a code.
Consequence: Agents and client code cannot reliably branch on errorCode — sometimes it's the discriminator, sometimes it's absent and you must string-match the human-readable message, which is itself "typically" but not always present. Error handling built against the documented examples will throw on the cases that omit errorCode.
The fix: Either guarantee errorCode on every error response and document the full enum, or publish an explicit table of which HTTP statuses include errorCode versus which only return message, so consumers know what's safe to parse.
6. Three different endpoint conventions across the API docs, with no single map (significant)
Location: https://docs.coveo.com/en/1445 (Search API), https://docs.coveo.com/en/78 (Push API), https://docs.coveo.com/en/56 (search tokens)
Problem: The docs present three incompatible host conventions for the same platform: the Search API uses org-specific hosts (https://<orgid>.org.coveo.com/..., HIPAA <orgid>.orghipaa.coveo.com); the Push API "still uses region-specific endpoints" (api.cloud.coveo.com, api-ca…, api-eu…, api-au…, apihipaa…); and the search-token page uses platform.cloud.coveo.com. The word "still" on the Push page signals other APIs migrated to org/unified hosts while Push did not, but there's no consolidated reference reconciling the three.
Consequence: A developer wiring up multiple Coveo APIs has to discover, per API, which of three host schemes applies — and a multi-region or HIPAA org multiplies the variants. Guessing wrong yields connection failures that look like auth or network errors.
The fix: Publish one "Organization endpoints" matrix that states, per API (Search, Push, Platform/token), the exact host pattern for standard, multi-region, data-residency, and HIPAA deployments — and link every API page to it instead of restating partial rules locally.
7. Two parallel auth-overview pages and three token types with three lifetimes (significant)
Location: https://docs.coveo.com/en/102 (Search API auth), https://docs.coveo.com/en/n3ge4046 (REST APIs auth), https://docs.coveo.com/en/56, https://docs.coveo.com/en/123
Problem: Two similarly-named top-level auth pages describe two different token systems: /en/102 lists "Search token authentication," while /en/n3ge4046 lists "Platform token authentication" and notes "The Search API uses separate methods." Meanwhile three token concepts carry three different lifetimes with no comparison table: search tokens expire after 24 hours (/en/56), browser-session access tokens are valid "up to four hours" (/en/123), and platform tokens are described only as "expiring" (/en/n3ge4046).
Consequence: "Search token" vs "platform token" is a terminology collision — a reader who lands on the wrong overview page implements the wrong token flow for their API. And conflating the 24h vs 4h lifetimes (easy, since both are "expiring tokens") leads to sessions that expire far sooner or later than expected.
The fix: Add a single token-comparison table (token type → which API → how you obtain it → default lifetime → intended use) and cross-link the two auth-overview pages with a one-line disambiguation at the top of each ("Looking for Search API tokens? See …").
8. Push API .md mangles the multi-region request blocks (significant)
Location: https://docs.coveo.com/en/78.md (Push API reference)
Problem: The AsciiDoc collapsible/tab structure degrades into stray markdown in the .md export: a code fence renders as a literal heading #### ```http, region labels appear as #### .Canada region, and ### Details repeats as an undifferentiated heading before each of the Ireland, Australia, and HIPAA endpoint blocks. The region-to-endpoint association (api-ca, api-eu, api-au, apihipaa) is only inferable from reading order, not structure.
Consequence: An agent parsing the .md to find "the Canada Push endpoint" sees a flat run of ### Details headings and stray fences, with no reliable way to bind a region name to its host. Combined with finding #6, this makes the most endpoint-sensitive API the hardest to parse.
The fix: Fix the AsciiDoc→markdown conversion for [%collapsible%] tabs so each region becomes a clean labeled section with a fenced HTTP block, and verify the four regional Push endpoints render as distinct, attributable code blocks.
9. List fields section anchors to v3 while its prose describes v1, and that link is dead in .md (significant)
Location: https://docs.coveo.com/en/p7lg0496.md (Version differences)
Problem: On /fields normalization, the comparison table (/fields endpoint normalization: v1 "Yes", v2 "No", v3 "No") and the prose ("This endpoint only performs normalization on the v1 route") agree — both say v1-only. The defect is structural, not a contradiction: the "List fields" section header links the operation to #tag/Search-V3 (a v3 anchor) even though the section text describes v1 behavior, and that link sits on a .md URL (/en/13.md#tag/Search-V3/operation/fieldsV3) that 404s (see finding #2). The same .md table also carries conversion artifacts — a 2+| colspan leftover and an undifferentiated dump of ~250 sys fields. The page does document a real gotcha worth surfacing more loudly: top-level fields "are returned twice… lowercase… and capitalized" (e.g. title and Title).
Consequence: A reader who follows the List fields anchor to confirm which version normalizes /fields lands on a dead .md link pointing at the wrong version, and the mangled table makes the v1/v2/v3 matrix hard to read in the agent-facing export. The double-return of title/Title is documented but buried, so anyone deduplicating field lists can still miss it.
The fix: Point the List fields section anchor at the version its prose actually describes (and at a URL that resolves in .md), remove the colspan/sys-dump artifacts from the .md table, and promote the title/Title double-return to an explicit callout rather than a trailing prose line.
10. Answer API navigation label doesn't match where its reference lives (minor)
Location: https://docs.coveo.com/en/p3ob0090.md (Answer API, open beta)
Problem: The nav lists "Answer API" as its own top-level item, but the reference link points to https://docs.coveo.com/en/3430.md#tag/Answer — i.e. the Answer reference is a tag under the Customer Service API, not a standalone API. The .md target (/en/3430.md) is itself a Swagger-backed page; if it follows the same pattern as the Search and Index references in finding #2 it would also 404, but /en/3430.md was not directly tested, so treat that as inference rather than a confirmed dead link.
Consequence: A reader who expects a dedicated "Answer API" reference instead lands inside the Customer Service API doc, which is confusing when deciding scopes/privileges and which API client to use.
The fix: Rename the nav entry to reflect that Answer is part of the Customer Service API (or add a one-line note on the Answer page: "The Answer API reference is documented under the Customer Service API"), and verify whether /en/3430.md resolves before relying on it as the .md cross-reference target.
11. Placeholder page "No syntax block" shipped in the Search API section (minor)
Location: https://docs.coveo.com/en/52.md (Use the Search API), child-article list
Problem: The list of child articles includes an entry literally titled "No syntax block" between "Get query suggestions" and "Get recommendations" — a placeholder or mis-titled page that escaped into the published navigation.
Consequence: Readers and agents see a meaningless nav entry and can't tell what it documents; it erodes trust that the section is complete and curated.
The fix: Rename the page to its intended title (or remove it) and add a check that flags placeholder strings like "No syntax block" before publish.
12. Query security basics opens mid-thought and asserts an unexplained identity model (minor)
Location: https://docs.coveo.com/en/127.md (Query security basics)
Problem: The page begins lowercase, mid-sentence — "indexes in the Coveo Platform support item-level security…" — and states "Each time a query is executed, the Coveo Platform associates this query to a unique email address" without defining how anonymous or public search fits the model.
Consequence: A developer implementing public/unauthenticated search can't tell whether a "unique email address" is mandatory, what identity is used for anonymous users, or how this interacts with search tokens — a gap in the security model's foundational page.
The fix: Open with a complete topic sentence and add a short paragraph (or link) explaining the identity used for anonymous/public queries versus authenticated users.
13. Many REST APIs ship with "Guide: N/A" — reference only, no how-to (minor)
Location: https://docs.coveo.com/en/143.md (Coveo REST APIs overview)
Problem: The overview table marks "Guide: N/A" for a substantial set of APIs — Activity, Machine Learning Configuration, Migration, Organization, Schema, Search Interface, Search Pages, Search Usage Metrics, and Source Logs — meaning those APIs have a reference but no task-oriented guide.
Consequence: For roughly a third of the REST surface, a developer gets endpoint definitions with no worked example of how to use them end-to-end, which is exactly the context agents and newcomers rely on to assemble a correct call.
The fix: Prioritize at least a minimal "common task" guide for the highest-traffic of these (Organization, Schema, Activity), or explicitly state on the overview that these are reference-only and point to the closest related guide.
What they do well
- The case-sensitivity rule is stated once, clearly, and reinforced across pages ("the same value passed to different REST APIs must always be passed using the same case") — a genuinely useful cross-cutting contract.
- Testing-only token guidance is unusually responsible: the browser-session page explicitly forbids using copied tokens "in application code, backend services, continuous integration (CI), or scripts."
- The effort to be agent-friendly is real and ahead of most docs —
llms.txt,llms-full.txt, and per-page.mdexports — which is exactly why the export defects above are worth fixing rather than ignoring.
Top 3 recommendations
- Fix the
.mdgeneration pipeline end-to-end — preserve<placeholder>tokens in both headers and URL paths (finding #1), render Liquid loops before export (finding #3), and stop emitting.mdlinks to pages that 404 in.md(finding #2). This single pipeline is the root cause of the three most severe findings. - Publish one endpoints matrix and one token matrix — consolidate the three host conventions (finding #6) and the three token types/lifetimes (finding #7) into reference tables every API page links to, instead of restating partial rules locally.
- Add publish-time linting — flag stripped placeholders and collapsed
//paths, broken.mdcross-links, placeholder titles like "No syntax block," and field-name typos (permantentid) before they ship.