Bolti Documentation Audit
One-line summary: A well-organized table of contents wrapped around a hollow core — the central API Reference 404s, entire marketed sections are "coming soon" placeholders, and the pages that do have content contradict each other on built-in tools, default models, and the API path prefix.
1. The API Reference 404s while being linked across the docs (critical)
Location: /api-reference (and cross-links from /intro, /platform-concepts, /getting-started/overview, /conversation-intelligence/webhooks, /calling/making-outbound-calls, /tool-calling/workspace-http-tools, and others)
Problem: docs.bolti.co.in/api-reference returns HTTP 404 (page_not_found), yet "API Reference" is the linked destination for nearly every "exact request/response shapes → see the API Reference" pointer in the docs. The platform-concepts page instead cites a different host, api.bolti.co.in/reference, and that page renders empty except for the title "Bolti API Reference" — a JS-only spec with no server-rendered body and no discoverable OpenAPI file or llms.txt.
Consequence: Bolti markets itself as "Open API + open dashboards — everything you can do in the dashboard, you can do via the REST API," but there is no reachable endpoint reference. Every page that defers schema detail ("→ See API Reference for the exact endpoint and payload shape") dead-ends. A developer — or an AI coding agent trying to scaffold a client — cannot discover endpoints, parameters, or response shapes at all. With no OpenAPI spec and a JS-rendered page, agents get nothing parseable.
The fix: Publish the API Reference at the URL the docs actually link (/api-reference), and ship a static OpenAPI/Swagger spec plus an llms.txt/llms-full.txt so both humans and agents can index endpoints. If the canonical spec lives at api.bolti.co.in/reference, server-render it or provide a downloadable spec, and update the in-docs links to point there.
2. "How do I authenticate an API request?" points to an unreachable page (critical)
Location: /getting-started/workspaces-and-organizations
Problem: The one place that tells a developer how to authenticate says: "The currently active workspace is also baked into every API request you make — see API Reference → Authentication for the header your client should send." That anchor lives under /api-reference, which 404s (see Issue 1). No page in the scraped docs states the auth header name, the credential format, or how to obtain a token for REST calls. (This is downstream of Issue 1 — the same missing reference — but it is called out separately because authentication is the single highest-stakes gap and its fix is distinct: it needs an inline, reachable home regardless of where the rest of the reference lands.)
Consequence: A developer can read every conceptual page and still be unable to make a single authenticated API call, because the workspace header and auth scheme are documented only at a destination that doesn't resolve. This blocks the entire "build over the REST API" path the docs repeatedly promote.
The fix: Document authentication inline on a reachable page: the exact header(s) (workspace identifier + credential), token issuance flow, and a complete curl example with a real header block. Mark placeholder values explicitly (e.g. Authorization: Bearer <token>).
3. Pervasive "Coming soon" placeholders across marketed sections (critical)
Location: /customizations/multilingual, /customizations/knowledge-bases, /customizations/voice-cloning, all of /telephony/, all of /conversation-intelligence/ except webhooks, /resources/pricing, /resources/faq, /resources/changelog, /resources/status, /calling/call-statuses, /calling/hangup-codes, /enterprise/sub-accounts, /enterprise/organization-management, /tutorials/* (7 of 8)
Problem: A large fraction of the documented surface is empty stubs reading "Coming soon — This page is a placeholder. Content will be added shortly." These are not obscure corners; they are headline features cross-linked as authoritative from substantive pages. Multilingual ("Hindi, Indic languages… 140-series compliance") is a top-three differentiator on /intro and the linked "deeper guide" from /agent-setup/speech — and it's empty. The entire Telephony section (SIP trunking, buying numbers, connect-provider, inbound/outbound) is placeholder, despite SIP trunking being quickstart step 4. Knowledge Bases is referenced as working from /quickstart, /agent-setup/overview, and /agent-setup/preview — its reference page is empty.
Consequence: Onboarding flows route new users straight into dead ends. A developer following "Quick Start → connect your telephony provider → Knowledge Bases" hits placeholder after placeholder. The docs read as far more complete than they are, eroding trust the moment a reader clicks past the happy path.
The fix: Either hide unfinished pages from navigation and cross-links until they have content, or replace "Coming soon" with the minimum viable reference (even a short field list beats an empty stub). Prioritize the pages reached from onboarding: Telephony setup, Knowledge Bases, Multilingual, Pricing.
4. Built-in tools: docs disagree on how many exist (critical)
Location: /agent-setup/tools vs. /tool-calling/introduction and /tool-calling/end-call
Problem: /agent-setup/tools advertises three built-in tools: "Transfer call," "End call," and "Schedule callback." But /tool-calling/introduction says "Today this includes: cut_call," and /tool-calling/end-call states flatly: "Today, cut_call is the only built-in tool." So Transfer call and Schedule callback are documented as shipping built-ins on one page and as nonexistent on another. The same /agent-setup/tools page even calls the end-call built-in "End call" in its feature list and cut_call in its "What's next" block.
Consequence: A developer building call-transfer or callback flows will enable tools that don't exist, or waste time hunting for why "Transfer call" never appears in their agent. An AI agent reading both pages cannot resolve which built-ins are real and will generate config against phantom tools.
The fix: Pick one source of truth for the built-in tool catalog and reference it everywhere. State clearly which built-ins ship today (apparently only cut_call) and mark Transfer/Schedule callback as roadmap if not yet available. Use the canonical tool id (cut_call) consistently, with the human label in parentheses.
5. The public API path is inconsistent — /public/v1/ vs bare, and outbound-call disagrees on workspace scoping (critical)
Location: /tool-calling/workspace-http-tools and /tool-calling/testing-tools vs. /platform-concepts, /agent-setup/llm, /customizations/context-and-variables, /calling/overview
Problem: Two separate, compounding inconsistencies:
- Prefix split. Tool endpoints carry a prefix:
POST/GET/PUT/DELETE /public/v1/workspaces/{workspace_id}/toolsandPOST /public/v1/workspaces/{workspace_id}/tools/test. But agent, token, and variables endpoints are documented without it:POST /workspaces/{ws}/agents,PATCH /workspaces/{workspace_id}/agents/{agent_id},/workspaces/{ws}/agents/{id}/token,GET /workspaces/{workspace_id}/agents/{agent_id}/variables. - outbound-call can't agree whether it's even workspace-scoped.
/customizations/context-and-variablesshows a bare/outbound-call, while/calling/overviewshows/workspaces/{...}/outbound-call. So the same endpoint appears at two different roots — not just with/without/public/v1, but with/without the workspace segment entirely.
Consequence: A developer cannot tell whether the public API root is /, /public/v1/, or whether outbound-call lives under a workspace. A large share of requests will hit the wrong path and 404, and there's no reachable API Reference (Issue 1) to adjudicate. This is exactly the kind of contradiction an agent fails silently on — it picks one form and every call to the other family breaks.
The fix: Standardize on a single documented base path for the public API and apply it to every endpoint example, including outbound-call's workspace scoping. State the base URL once, prominently, and correct whichever page diverges.
6. The recommended MCP auth path — and the whole MCP "start here" chain — is empty (critical)
Location: /mcp/personal-access-tokens, /mcp/installation, /mcp/available-tools (referenced from /mcp/overview)
Problem: /mcp/overview is substantive and MCP-native is a top-three marketed differentiator, but it depends on three placeholder pages. It tells users "If this is your first time, start with Installation" (placeholder), routes the recommended auth flow to "Details: Personal Access Tokens" (placeholder), and says the server "registers around 40 tools" with the full list at "Available Tools" (placeholder). The overview references a tool name (auth_create_mcp_token) and an env var (MCP_BOOTSTRAP_TOKEN) documented nowhere else.
Consequence: "You'll be running tools from chat in about five minutes" is followed immediately by a link to an empty Installation page. The recommended personal-access-token flow has no instructions, and MCP_BOOTSTRAP_TOKEN is named but never explained (where it goes, how to issue/revoke it). Users can't enumerate the ~40 tools because the only page that would list them is blank. The headline MCP experience is unusable beyond the overview.
The fix: Fill Installation (Cursor/Claude Desktop config blocks), Personal Access Tokens (how to generate, where MCP_BOOTSTRAP_TOKEN goes, expiry/revocation), and Available Tools (the full ~40-tool reference). Until then, don't present them as the "start here" path.
7. Default LLM model contradicts itself across two pages (significant)
Location: /agent-setup/llm vs. /customizations/custom-llms
Problem: /agent-setup/llm says "The default for new agents is OpenAI / gpt-5-mini." /customizations/custom-llms labels gpt-4o-mini as "Bolti default for the wizard." Two pages, two different answers about the default model a new agent ships with. The model catalog also mixes future-looking ids (gpt-5.1, gpt-5-mini, gpt-5-nano, gemini-3.1-pro-preview, gemini-3-pro-preview) with current ids like gpt-4o and gemini-2.0-flash, compounding uncertainty about what's actually live.
Consequence: A developer reasoning about latency, cost, or quality can't trust either page's stated default. Anyone tuning prompts against "the default model" may be optimizing for the wrong one — gpt-5-mini and gpt-4o-mini are different models with different behavior.
The fix: State the real default once (in the LLM tab reference), and update custom-llms to match or to clearly mark its label as an example rather than the authoritative wizard default.
8. STT provider lists contradict each other, and a recommended STT provider isn't listed as one (significant)
Location: /getting-started/providers and /agent-setup/speech vs. /platform-concepts
Problem: /getting-started/providers and /agent-setup/speech both list Fennec as an STT provider ("Optimized for Indian languages," id fennec-asr). /platform-concepts STT list omits Fennec entirely (Deepgram, AssemblyAI, ElevenLabs, Cartesia, Azure). Separately, /getting-started/providers advises "Indian-language calls? Fennec or Sarvam-backed STT will outperform global vendors" — but "Sarvam-backed STT" is never listed as an available STT provider; SarvamAI appears only under TTS.
Consequence: A developer building Indian-language agents — Bolti's stated focus — gets conflicting answers on whether Fennec is selectable and is pointed at a "Sarvam STT" option that doesn't appear in any STT list. This directly undermines the multilingual selling point.
The fix: Reconcile the STT provider list across all three pages (add Fennec to platform-concepts if it's real). Either add Sarvam as a documented STT provider or remove the "Sarvam-backed STT" recommendation.
9. Webhook headers carry leftover "Voiceai" branding (significant)
Location: /conversation-intelligence/webhooks
Problem: Webhook signature headers are named X-Voiceai-Event and X-Voiceai-Signature — "Voiceai," not "Bolti." These header names are a contract clients must match exactly to verify signatures, and they suggest the product was renamed or forked without updating the header scheme.
Consequence: Header names are not cosmetic — a developer implementing signature verification must read the exact header string. The branding mismatch reads as a bug or a stale doc, and any reader who "corrects" X-Voiceai-* to X-Bolti-* (assuming a typo) will fail verification. Conversely, if the runtime now emits X-Bolti-*, the docs are wrong. Either way, signature verification is at risk.
The fix: Confirm the actual header names the runtime emits and document them verbatim. If the platform was rebranded from "Voiceai," update both the runtime and the docs so the contract is consistent — and add a note for existing integrations if the headers changed.
10. Pricing is cited as authoritative from multiple pages but is a placeholder (significant)
Location: /resources/pricing (referenced from /getting-started/providers, /getting-started/overview, /calling/making-outbound-calls, /calling/overview)
Problem: Multiple pages defer the actual cost model to a pricing page: providers says "See exact rates on the pricing page," getting-started/overview says "The pricing page breaks down exactly how the per-minute cost is calculated," and making-outbound-calls/calling-overview point to Pricing for credit costs. That page reads only "Coming soon — This page is a placeholder."
Consequence: Bolti's billing model is usage-based and bundles STT/LLM/TTS/telephony into a per-minute rate, but the documented "transparent per-minute rate" is nowhere quantified. A developer or buyer cannot estimate cost before placing real calls, despite being told repeatedly that the math is "broken down" on a page that's empty.
The fix: Publish the per-minute rate structure (or a clear "contact us" with ranges). Don't promise an exact-rate breakdown until the page exists.
11. Promised tutorials are mostly empty, and one major feature is documented only inside a tutorial (significant)
Location: /tutorials/* and /tutorials/hr-screening-recipe
Problem: The intro promises "Tutorials — End-to-end recipes (Google Sheets, Zapier, Make.com, full agent builds)," and an outbound sales recipe is explicitly promised via the page "Build an Outbound Sales Agent." Yet 7 of 8 tutorial pages are placeholders, including /tutorials/outbound-sales-recipe and /tutorials/support-agent-recipe. The single real tutorial, HR Screening, documents a significant dashboard feature ("Agents → HR Screening") that no other doc page mentions — its existence, template variables ({{ candidate_name }}, {{ jd_text }}, etc.), and Cal.com/n8n webhook wiring (CALCOM_WEBHOOK_SECRET) live only inside a tutorial.
Consequence: The promised end-to-end recipes don't exist, and a non-trivial product surface (HR Screening) is discoverable only by accident. Its "Related" links point to placeholder pages (Call Statuses, Transcripts), so even the one good tutorial dead-ends. Developers can't find the feature, and can't follow the recipes the homepage advertises.
The fix: Either ship the promised recipes or remove them from the marketing list until ready. Give HR Screening a first-class reference page under Agent Setup, and fix the tutorial's Related links to point at live content.
12. Call lifecycle is defined inline but the canonical status/hangup references are empty (significant)
Location: /calling/call-statuses and /calling/hangup-codes (referenced from /calling/overview, /calling/making-outbound-calls, /tutorials/hr-screening-recipe)
Problem: /calling/overview and /calling/making-outbound-calls each define partial call-state and error behavior inline (e.g. the outbound error table: 400/402/403/429; an Idempotency-Key/409 Conflict behavior; a 402 PAYMENT_REQUIRED mention), while the canonical references — Call Statuses and Hangup Codes — are both placeholders. "Diagnose why a call hung up → Hangup Codes" leads to an empty page, even though /calling/overview says every conversation carries "a hangup code when the call ends."
Consequence: When a production call fails, the developer is told to consult Hangup Codes and Call Statuses to interpret the result — and finds nothing. The partial, inline status lists risk diverging from each other with no authoritative reference to reconcile them. This is precisely the production-debugging path that needs to be airtight.
The fix: Populate Call Statuses (every lifecycle state) and Hangup Codes (termination reasons + provider codes) as the single source of truth, and have the inline tables link to them rather than duplicate them.
13. "Assistants" in the dashboard vs. "agents" in the docs (minor)
Location: /getting-started/quickstart
Problem: The quickstart says "From the dashboard home (the Assistants page), click Create AI Agent," while every other page calls the objects "agents." The dashboard's primary noun ("Assistants") doesn't match the docs' noun ("agents").
Consequence: A new user toggling between the docs and the UI has to infer that "Assistants" and "agents" are the same thing. Minor, but it adds friction exactly at first-run, and an AI agent mapping doc terms to UI labels may treat them as distinct entities.
The fix: Align terminology — either rename the dashboard section to "Agents" or add a one-line note in the docs that the Assistants page is where agents live.
14. Documented tool fields are silently ignored by the runtime (minor)
Location: /tool-calling/workspace-http-tools
Problem: The page documents two tool fields — Response Schema and Response Path — then notes "Bolti's voice runtime currently does not slice or validate the response with them. The full HTTP response body is handed back to the LLM as-is… Future versions will honor it; today the model sees the whole body."
Consequence: This is honestly disclosed (good), but it's still a doc-vs-behavior trap: a developer who sets a Response Path expecting data.order.status extraction will instead get the entire response body fed to the model, with no runtime error. The "stored but ignored" semantics are easy to miss in a longer page.
The fix: Add an inline callout/badge ("Stored as documentation only — not yet enforced") directly on the field labels, not just in a paragraph below, so the no-op behavior is unmissable.
15. Future-dated model ids with no changelog or version history (minor)
Location: /agent-setup/llm, /customizations/custom-llms, /resources/changelog
Problem: The model catalog lists ids like gpt-5.1, gpt-5-mini, gpt-5-nano, gemini-3.1-pro-preview, and gemini-3-pro-preview alongside current ids like gpt-4o. There is no dated changelog (the /resources/changelog page is a placeholder) and no version stamps anywhere in the docs.
Consequence: A developer can't tell which models are actually available today versus aspirational, and there's no changelog to check when the catalog changes. Mixing clearly-current (gpt-4o) with forward-looking ids, undated, makes the whole table hard to trust.
The fix: Mark each model's availability status (GA / preview / planned), and publish a dated changelog so the catalog's currency is verifiable.
16. The /intro "How to read this" persona table is missing a cell (minor)
Location: /intro
Problem: The "How to read this" persona table has three rows, but the third — "An agency / platform team building for clients" — has no "Read this first" cell. The row terminates after the persona label with an empty right-hand column, while the founder/PM and developer rows both have a populated reading path.
Consequence: The exact audience most likely to be doing serious integration work (agencies/platform teams building for clients) is given a navigational starting point of nothing. It also reads as a truncation bug on the literal first page a reader lands on, which undercuts confidence in the rest of the docs before the reader has clicked anything.
The fix: Fill the third row's "Read this first" cell with a reading path (e.g. Platform Concepts → Enterprise → Sub-Accounts → API Reference), or remove the half-populated row until there's content for it.
17. Template syntax is called both "Jinja" and "Liquid" for the same {{ }} braces (minor)
Location: /tutorials/hr-screening-recipe vs. /customizations/context-and-variables
Problem: The HR-screening recipe tells authors to reference template variables "with Jinja-style braces" ({{ candidate_name }}, {{ jd_text }}, etc.), while the context-and-variables page describes the same {{ }} variable syntax as Liquid. Jinja and Liquid are different templating engines with different filters, escaping rules, and conditional/loop semantics.
Consequence: A developer writing a prompt template can't tell which engine's rules apply — whether a filter like | default: or | upper behaves as Liquid or Jinja, or whether conditionals use Liquid's {% if %} semantics or Jinja's. Guessing wrong produces prompts that silently render incorrectly rather than erroring.
The fix: Name one templating engine and use it consistently across both pages, with a short list of the filters/tags actually supported so authors aren't guessing across two incompatible dialects.
What they do well
- The pages that have content are genuinely good — /calling/making-outbound-calls has a clean error table plus idempotency semantics (
Idempotency-Key→409 Conflict), and /conversation-intelligence/webhooks documents signature verification concretely. - Honest about gaps in shipped features — pages explicitly flag not-yet-enforced fields (Response Schema/Path) and roadmap items (interruption-sensitivity tuning) rather than overstating them.
- Per-section "Where to go next" routing tables are a sound navigational pattern — the per-section next-step tables give the docs a usable skeleton, and would be a real strength once their destinations exist and the /intro persona table (Issue 16) is complete.
Top 3 recommendations
- Restore the API Reference and document auth inline. Ship the reference at
/api-reference(the URL the docs link), publish a static OpenAPI spec +llms.txt, and put the authentication header/token flow on a reachable page. This unblocks the entire "build over the REST API" pitch. - De-placeholder or de-link. Remove "Coming soon" pages from navigation and cross-links until they have content — especially Telephony, Knowledge Bases, Multilingual, Pricing, and the MCP start-here chain — so onboarding stops routing users into dead ends.
- Reconcile the contradictions. One source of truth each for: built-in tools (
cut_callonly vs. three), the API path (/public/v1/vs bare, and outbound-call's workspace scoping), the default LLM model (gpt-5-minivsgpt-4o-mini), and the STT provider list. These are the failures that break AI agents silently and cost human developers the most debugging time.