Extensive, professionally maintained REST/SDK documentation whose biggest weakness is internal disagreement: the authentication and token pages contradict each other on endpoints, expiration, privilege names, and error bodies — and the agent-facing .md/llms.txt contract is silently violated on more than one page.
1. Search-token endpoint gains and loses a /v2 segment between two pages (critical)
Problem: The two pages document the same operation against different paths. Page 56: POST https://<ORG_ID>.org.coveo.com/rest/search/v2/token?organizationId=<ORG_ID>. Page 1369: Make a POST request to https://<ORG_ID>.org.coveo.com/rest/search/token (no /v2), with a worked example POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/token.
Consequence: A developer — or an AI agent extracting the endpoint — has a 50/50 chance of constructing the wrong URL. One of these paths is wrong; the token pages give no signal which. Humans discover it via a 404/error; agents fail silently and emit a broken integration.
The fix: Standardize the token route across pages 56 and 1369. The canonical "Perform a query" page (1445) documents the Search API base as <ORG_ID>.org.coveo.com/rest/search/v2, supporting the /v2 form — though note the Organization endpoints page (mcc80216) shows /rest/search without /v2 for queries, so the query base itself disagrees too. Pick one path, make every token example use it verbatim, and add it to the OpenAPI spec so there is one source of truth.
2. "An API key is a non-expiring access token" contradicts the API-key expiration rules (critical)
Location: /en/1369/ (API key authentication) vs. /en/1718/ (Manage API keys)
Problem: Page 1369 opens: "An API key is a non-expiring access token which carries a certain set of privileges." Page 1718 documents the opposite at length: "You must set an expiration date of 1, 7, or 14 days when you create a key using this [View all content] template," and "[you can't reactivate] keys that have expired."
Consequence: A developer reading page 1369 will architect on the assumption that keys never expire — no rotation, no renewal handling — then ship a key (View all content / Custom template) that dies in as little as 1 day and silently breaks production with no fallback.
Code verification
Runtime snippet checks
Run the public examples from this audit in an isolated sandbox and attach the pass, fixed, skipped, and failed counts to the report.
The fix: Correct page 1369 to "An API key is an access token that may or may not expire depending on its template," and link directly to the expiration section of page 1718.
3. llms.txt promises fully-resolved .md files, but at least two pages ship unresolved source (critical)
Location: /en/llms.txt contract vs. /en/q2ib0310.md (Deprecations) and /en/56.md (Use search token authentication)
Problem: llms.txt states the per-page .md source files have "all includes resolved, conditionals evaluated, and glossary terms expanded to plain text." Two pages violate this:
q2ib0310 (Deprecations): the .md contains raw, unrendered Liquid where the table should be — {% assign by_order = site.deprecations | where_exp... %} … | {{ notice.deprecation-date }} | [{{ notice.title }}]({{ site.baseurl }}/{{ notice.slug }}/) |. The live HTML renders deprecation notices with end-of-support dates (kernel-verified); the .md an agent ingests contains zero notices and zero dates.
Page 56: the .md carries unresolved link placeholders — [API Key]({site-baseurl}:1718), {site-baseurl}/1445/, {site-baseurl}/13/api-reference/… — i.e. includes/links that the contract promises are resolved. (This second instance is in the scraped .md; confirm against the live export that it isn't a downstream extraction artifact before publishing the fix, but it points at a systemic, not one-off, export gap.)
Consequence: AI coding agents — the explicitly-targeted consumers of these .md files — get an empty answer for "what's deprecated / when does support end," the single most safety-critical page for migration planning, and get dead {site-baseurl} link targets on the search-token page. The contract assures them both are complete.
The fix: Render Liquid and resolve {site-baseurl} link includes before exporting .md, or exclude pages that can't be statically rendered from the .md contract. Either way, the llms.txt promise must match what the files actually contain.
4. On the token page, the "Important" callout names an endpoint the examples never use (significant)
Problem: The callout reads: "The examples on this page use the standard Coveo endpoint (platform.cloud.coveo.com)." Every token-request example on the page actually targets the org-specific host — const tokenEndpoint = https://${orgId}.org.coveo.com/rest/search/v2/token... and POST https://<ORG_ID>.org.coveo.com/rest/search/v2/token. The only platform.cloud.coveo.com references on the page are the IPX loader and Swagger links.
Consequence: A reader trusting the callout will try to send token requests to platform.cloud.coveo.com, which is not what the working code uses; the prose and the copy-paste code disagree about the host on the very page meant to teach the flow.
The fix: Update the callout to describe the <ORG_ID>.org.coveo.com endpoint the examples actually use, and reserve the multi-region/HIPAA caveat for the linked Organization endpoints page (mcc80216).
5. "Authenticated Search scope" terminology doesn't exist in the API-key model (significant)
Location: /en/56/ footnote <2> vs. /en/1718/ (Manage API keys)
Problem: Page 56 instructs: "Replace this value with an API Key that has the 'Authenticated Search' scope." The authoritative key-management page (1718) has no concept of "scope" — keys are built from templates tagged "Can be public" or "Must remain private," one of which is named "Authenticated search." There is no scope picker in the described UI.
Consequence: A developer searches the Administration Console for an "Authenticated Search scope" setting, finds none, and stalls. Agents inherit a term that maps to nothing in the product's actual data model.
The fix: Replace "scope" with "template" on page 56: "an API key created from the Authenticated search template." Audit the docs for other uses of "scope" in the API-key context.
6. The same analytics privilege is named two different things on one page (significant)
Location: /en/1369/ (API key authentication)
Problem: Within a single page, the privilege a key needs to send analytics is given two different names. The primary instruction: create a key with "Search - Execute queries and Analytics - Analytics data - Push" privileges. A few paragraphs later, the public-key scenario: "expose a public API key with Search - Execute queries and Analytics - Analytics data - Edit privileges."
Consequence: A developer configuring the key in the Console can't tell whether to grant "Push" or "Edit" for Analytics data. Because the conflicting instruction is for the public-key branch — a key exposed in client-side code — granting the wrong, broader access level here is a security exposure, not just a broken write. (Page 1718's Anonymous-search template lists "Analytics data: Push," suggesting "Push" is correct and "Edit" is the error.)
The fix: Standardize on the real privilege name throughout page 1369, and cross-check it against the template definitions on 1718 so the public-key branch grants the minimum required level.
7. The Search API 429 resolution tells you to throttle the wrong API (significant)
Location: /en/1471/ (Search API error codes), section "429 TOO_MANY_REQUESTS"
Problem: The page documents 429s returned by the Search API ("The Search API returns an error concerning too many requests being made to the Search API"), but the resolution says: "In the future, ensure that you make Push API calls at a slower pace."
Consequence: A developer hitting Search API throttling is sent to fix Push API call rates — an unrelated subsystem — and never addresses the actual query-rate problem. The fix advice doesn't match the error being documented.
The fix: Change the resolution to reference Search API request pacing (and link to Search API rate-limit guidance), not the Push API.
8. The 419 "expired token" response body differs between the two pages that document it (significant)
Location: /en/56/ (Renew expired search tokens) vs. /en/1471/ (Search API error codes, "419 Expired token")
Problem: The two pages publish different JSON for the same 419. Page 56: { "message": "Expired token", "statusCode": 419, "type": "ExpiredTokenException" }. Page 1471: { "statusCode": 419, "message": "Search token has expired." } — different message string and no type field at all.
Consequence: Anyone writing error-handling code that matches on message text or branches on the type field will match one page's contract and silently fail against the real response. Page 1471 even concedes its errorCode field "may not appear in all error responses," compounding the unreliability of matching on these bodies.
The fix: Document the exact response the API returns (verified against a live 419), make both pages identical, and tell readers which fields are guaranteed vs. best-effort so they match on stable fields.
9. Two near-identically-titled "Authentication methods" pages describe different method sets (significant)
Location: /en/102/ ("Search API authentication methods", build-a-search-ui) vs. /en/n3ge4046/ ("Authentication methods", apis)
Problem: Page 102 lists: API key, Search token, Claims, SAML. Page n3ge4046 lists: API key, Platform token, "Coveo access token from a browser session." The two pages cover different concepts, and the only disambiguation is one inline note on n3ge4046 ("The Search API uses separate methods..."). "Search token" and "Platform token" are different things that sound interchangeable.
Consequence: A developer landing on either page from search has no reliable way to know whether they're reading the right one, and may implement "platform token" flow for a search interface that actually needs a "search token" (or vice versa). Agents conflate the two token types.
The fix: Page 102 is already scope-qualified as "Search API authentication methods"; the generic page is n3ge4046, titled simply "Authentication methods." Retitle n3ge4046 to be scope-qualified (e.g. "REST Platform API authentication methods") and add a short comparison table clarifying search token vs. platform token up front on both pages.
10. The APIs index lists "Customer Service API" twice and labels other entries with non-identifying titles (minor)
Location: /en/llms/sections/apis.txt
Problem: The APIs section index contains two separate "Customer Service API" entries pointing at different slugs (3321 and 3430), plus entries whose titles don't identify the API they document: "Usage" → 3326 and "Reference" → 4.
Consequence: A reader (or agent) browsing the API list can't tell which "Customer Service API" page is current/canonical, or what "Usage" and "Reference" actually reference, increasing the chance of landing on a stale or wrong page.
The fix: Deduplicate the two Customer Service API entries (or distinguish them, e.g. "Customer Service API — Reference" vs. "Guide"), and rename generic entries to name their API ("Usage Analytics — Usage", "Search API — Reference").
11. Sample query response ships a misspelled field key permantentid (minor)
Location: /en/1445/ (Perform a query), "200 OK response body (excerpt)"
Problem: The sample response object contains "permantentid": "ecc3fac2...". Coveo's actual result field is permanentid. The misspelling is in the documented response, not flagged as an example artifact.
Consequence: A developer (or agent) who models result parsing on this excerpt will read result.raw.permantentid, get undefined against real responses, and debug a typo that originated in the docs rather than their code.
The fix: Correct permantentid → permanentid in the sample body.
12. Endpoint-deprecation callout has a tense error in the one sentence that signals breaking changes (minor)
Location: /en/mcc80216/ (Organization endpoints), top "Important" callout
Problem: "On June 3, 2025, Coveo deprecated older endpoints and make other endpoint-related changes." Should be "made."
Consequence: Low functional impact, but the grammar slip sits in the highest-stakes callout on the page — the one warning readers their implementation may already be broken — which undercuts its authority.
The fix: "deprecated older endpoints and made other endpoint-related changes."
13. The product-news hub carries no dates, giving no recency signal (minor)
Location: /en/3378/ (Coveo product news)
Problem: The product-news hub is a bare link list with no dates on any entry — "New Coveo Platform features," the framework change-logs, and the integration entries all appear without a last-updated or coverage-window indicator. As of mid-2026, a reader on this hub has no way to tell whether the linked pages reflect current-year changes or stale ones.
Consequence: A developer auditing what changed recently can't confirm from the hub whether they're seeing current information, and must click into each undated child page to find out.
The fix: Add last-updated dates (and, where applicable, a coverage window) to the entries on the news hub, and state explicitly where current-year platform changes live so readers don't have to guess between the rolling "New Coveo Platform features" page and any annual archives.
What they do well
A real machine-readable contract exists: llms.txt / llms-full.txt, a flat page index, per-page .md source files, and a generated Swagger UI — more agent-facing infrastructure than most platforms ship.
The case-sensitivity rule is stated once, canonically, on the REST APIs overview (page 143) and framed for cross-API consistency.
Security guidance for client-side keys (page 105) is clear and prescriptive: use the Anonymous search template, never expose a "Must remain private" template, switch to search tokens for secured content.
Top 3 recommendations
Reconcile the authentication pages against a single source of truth. The token endpoint (/v2 or not), API-key expiration, the "scope" vs "template" vocabulary, the Push/Edit privilege name, and the 419 body all disagree across pages 56, 1369, 1471, and 1718. Drive them all from the OpenAPI spec and the template definitions.
Make the .md/llms.txt contract true. Render Liquid and resolve {site-baseurl} link includes before export (the Deprecations page ships raw template code; page 56 ships unresolved link placeholders), or exclude pages that can't be statically rendered — agents are explicitly told these files are complete.
Fix the wrong-API and wrong-host instructions. The 429 resolution points at the Push API on a Search API page; the token page's callout names a host its own examples never use. Both send readers to debug the wrong thing.