Google Gemini API Documentation Audit
The Gemini API docs are vast and recently overhauled around the Gemini 3 family, but the rollout has left model names, code samples, schema shapes, and dated deadlines out of sync across pages — a serious problem for AI coding agents that take each page at face value.
1. Home page promotes a model that doesn't appear in the Models index (critical)
Location: /gemini-api/docs (home), /gemini-api/docs/models
Problem: Every code sample on the Gemini API home page uses model="gemini-3.5-flash" and the home's "Meet the models" tiles tag "Gemini 3.5 Flash" as New. But the /models page renders a top-level ## Gemini 3 heading with no models listed beneath it — the next visible card is Gemini 2.5 Flash. Gemini 3.5 Flash only resurfaces buried in the Audio/Batch sub-sections and the "Model version name patterns" example still uses gemini-2.5-flash.
Consequence: A developer (or coding agent) clicking from the home page's gemini-3.5-flash snippet to "see all models" finds an empty Gemini 3 section and a 2.5-era version-naming example. They cannot confirm gemini-3.5-flash is a real, stable ID, what its context window is, or what its preview alias is. Agents that consult the Models page for canonical IDs will silently regress to gemini-2.5-flash.
The fix: Populate the ## Gemini 3 section with model cards for the three models advertised on the home page. First reconcile naming between surfaces — the home tile says "Gemini 3.1 Pro" while the pricing and deprecations pages both use gemini-3.1-pro-preview — then publish the canonical ID + display name pair on the models index and use it consistently. Update the version-naming example to use a Gemini 3 model.
2. Home page capability blurb references a wholly different model than the section title (critical)
Location: /gemini-api/docs — "Explore Capabilities" → "Native Image Generation"
Problem: The capability tile is titled "Native Image Generation (Nano Banana)" and the "Meet the models" section above promotes "Nano Banana 2 and Nano Banana Pro" as New. But the blurb under the same tile says "Generate and edit highly contextual images natively with Gemini 2.5 Flash Image." Three different model identities for one feature on a single page.
Consequence: Agents and developers cannot tell which model ID to actually pass to generateContent for image generation: Nano Banana? Nano Banana 2? Nano Banana Pro? Gemini 2.5 Flash Image? gemini-3.1-flash-image-preview (the ID used on the pricing page)? Each maps to a different price and capability set.
The fix: Pick one canonical model ID per capability tile and use it consistently. The image-generation blurb should reference gemini-3.1-flash-image-preview (the ID priced on /pricing) and link to it; "Nano Banana" branding should appear alongside the technical ID, not in place of it.
3. Files API contradicts itself on the 100 MB cutoff (critical)
Location: /gemini-api/docs/files
Problem: The Upload section says: "Always use the Files API when the total request size … is larger than 100 MB." The same page's "Usage info" describes a 20 GB project quota with a 2 GB per-file maximum. The page never explicitly states the inline base64 request body cutoff — i.e., the threshold below which inline parts are legal. So which is the inline-request ceiling — something less than 100 MB? 100 MB itself? The page does not say.
Consequence: Developers building upload paths cannot reliably gate "use Files API vs. inline parts" without trial-and-error 4xx errors. Agents generating upload logic from this page will pick a threshold and be wrong on at least one of the call sites.
The fix: State the inline request body cutoff explicitly in a single table at the top of the page alongside the Files API per-file max (2 GB) and the project storage cap (20 GB). Make clear which limit applies to which call path.
4. Rate-limits tables duplicate Gemini 3.5 Flash rows in every tier (significant)
Location: /gemini-api/docs/rate-limits — Batch API Tier 1, Tier 2, Tier 3 tables
Problem: Every Batch-API tier table lists Gemini 3.5 Flash twice with identical values:
| Gemini 3.5 Flash | 3,000,000 |
| Gemini 3.5 Flash | 3,000,000 |
There is no Preview/GA distinction or other column to explain the duplicate. The same tables also contain bare | --- | --- | --- | --- | rows where Text-out models / Multi-modal generation models / Embedding models subgroup headers should be.
Consequence: Programmatic readers (rate-limit planners, agents budgeting batch quota) cannot tell whether 3.5 Flash has 3M, 6M, or some Preview-specific quota. The broken table markdown also means anyone trying to scrape or render the page sees unlabeled separator rows.
The fix: Either deduplicate the row or add a "Tier variant" column (GA vs Preview) that explains the second entry. Convert the orphan separator rows into proper subgroup <thead> rows so the table is parseable.
5. Structured-output Go sample uses a schema shape that contradicts Python/JS on the same page (critical)
Location: /gemini-api/docs/structured-output
Problem: The Python example passes:
config={"response_format": {"text": {"mime_type": "application/json", "schema": Recipe.model_json_schema()}}}
The JS sample uses the matching new shape (responseFormat: { text: { mimeType: ..., schema: ... } }). But the Go sample on the same page uses a different shape:
ResponseMIMEType: "application/json",
ResponseJsonSchema: map[string]any{...}
The changelog (May 6, 2026) labels the schema/response_format change a breaking change with the legacy shape being removed June 8 — which makes the Go sample either an oversight from the migration or a deliberate Go-specific exception, and the page does not say which.
Consequence: Developers porting between languages copy the Go shape into Python (or vice versa) and get 400 errors. If the Go sample is using the soon-to-be-removed legacy shape, it silently breaks for anyone who copied it after June 8. Coding agents reading the page see two different "correct" answers depending on which language they look at first.
The fix: Either bring the Go sample into the new response_format shape that matches Python and JS, or add a callout explaining the Go-SDK-specific difference. Link the May 6, 2026 migration guide inline.
6. OpenAI-compatibility Python example double-nests extra_body (critical)
Location: /gemini-api/docs/openai — Thinking → Python (extra_body)
Problem: The Python snippet writes:
extra_body={
'extra_body': {
"google": { "thinking_config": { ... } }
}
}
The JS sample directly below shows the correct single-nested form: extra_body: { "google": { ... } }. The Python version has an extra 'extra_body' key wrapping the Google block.
Consequence: Anyone copying the Python snippet sends extra_body.extra_body.google.thinking_config to OpenAI's client, which forwards it to Gemini, which doesn't see a top-level google field — thinking config is silently ignored. The user gets default thinking behavior and a bill they didn't expect, with no error message pointing at the problem.
The fix: Remove the inner 'extra_body' key from the Python sample so it matches the JS structure. Add a test that round-trips this snippet through the OpenAI client.
7. REST example response has invalid JSON and a misleading candidate index (significant)
Location: /api/rest — Response examples
Problem: Two issues on one page. (a) The "standard" sample response shows a single-candidate array with "index": 1 for the only candidate — but the streaming example on the same page uses "index": 0 for the first candidate, so the reference contradicts itself. (b) The streaming JSON example's second chunk has a missing comma:
"usageMetadata": {
"promptTokenCount": ...
} <-- missing comma
"modelVersion": "gemini-3.5-flash",
The displayed JSON does not parse.
Consequence: Anyone writing a parser against the REST reference cannot tell whether candidates[0].index is 0 or 1. Anyone copy-pasting the streaming example into a JSON-mode unit test fails immediately. Agents that infer the schema from this page produce broken validators.
The fix: Set "index": 0 in the single-candidate example to match the streaming sample and add the missing comma after the usageMetadata object in the streaming chunk. Lint examples as JSON in CI.
8. Troubleshooting table omits 401 and undersells Temperature range (significant)
Location: /gemini-api/docs/troubleshooting
Problem: The backend-error table covers 400, 403, 404, 429, 499, 500, 503, 504 — but no 401 UNAUTHENTICATED row, even though missing/expired x-goog-api-key is one of the most common first-request failures. Separately, the "Model parameter errors" table caps Temperature at 0.0–1.0 with no qualifier, while community examples and sample notebooks routinely use higher values; the page does not document which model families honour what range.
Consequence: Developers seeing a 401 from the API go searching for it in the troubleshooting guide and find nothing — they assume it's a different problem (network, region, billing). The unqualified Temperature row means developers who copy known-working community values get warned off, and agents hard-cap at 1.0 in generated configs.
The fix: Add a 401 UNAUTHENTICATED row to the error table with the canonical cause (missing/invalid API key header). Replace the Temperature row with a per-model-family range pulled from the REST schema, or link out to the schema as the source of truth.
9. "Stale dates" — past deadlines presented as future, future deadlines unsurfaced (critical)
Location: /gemini-api/docs/api-key, /gemini-api/docs/deprecations, /gemini-api/docs/caching
Problem: Today is 2026-05-29 and several dated guarantees in the docs are simply wrong relative to the calendar:
- The API-key page writes the May 7, 2026 dormant-key block in future tense: "Starting May 7, 2026, the Gemini API will block unrestricted API keys that have been dormant." That date is three weeks in the past.
- The same page says "Starting June 19, 2026, … the Gemini API will discontinue support for unrestricted traffic keys." That is three weeks away — a near-term breaking change with no surface on the home page or troubleshooting guide.
- The Deprecations page lists models with shutdown dates already past:
gemini-2.0-flash-live-001(Dec 9, 2025),text-embedding-004(Jan 14, 2026),imagen-3.0-generate-002(Nov 10, 2025), andgemini-3-pro-preview(March 9, 2026). They are presented in the same "upcoming" table as live models. - The Caching page's minimum-token table still lists
Gemini 3 Pro Preview(gemini-3-pro-preview) as if usable; per the changelog and deprecations page it shut down March 9, 2026.
Consequence: Readers cannot trust dated language anywhere on the site without checking the calendar themselves. Code that targets gemini-3-pro-preview from the caching page errors out. Teams running on unrestricted API keys do not see a "3 weeks until your traffic stops" warning where they actually look (home, troubleshooting).
The fix: Rewrite past-tense deadlines in past tense ("On May 7, 2026 the Gemini API began blocking…"). Move shut-down models to a separate "Shut down" section instead of mixing them into upcoming deprecations. Replace gemini-3-pro-preview with gemini-3.1-pro-preview in the caching table. Surface the June 19, 2026 unrestricted-key cutoff on the home page and the 401-row addition recommended above.
10. Caching minimum-token table is missing most current models (significant)
Location: /gemini-api/docs/caching
Problem: The "minimum input token count for context caching" table lists only four models: Gemini 3.5 Flash, Gemini 3 Pro Preview, Gemini 2.5 Flash, Gemini 2.5 Pro. Missing: gemini-3.1-pro-preview, gemini-3.1-flash-lite, gemini-3-flash-preview, every image/video/embedding model. The same page also mixes the model='models/gemini-3.5-flash' prefix form and model_name="gemini-3.5-flash" (no prefix) across adjacent Python snippets, with no explanation of which form the SDK accepts where.
Consequence: Developers trying to enable implicit caching for gemini-3.1-pro-preview cannot find its minimum threshold and either over-provision context or assume caching doesn't apply. Anyone copying between the two Python snippets is guessing whether the models/ prefix is required.
The fix: Add rows for current Pro Preview, Flash-Lite, and any other supported family, plus an explicit "(no caching)" indicator for families that don't support it. Standardize on one model-ID form (with or without models/) across all Python snippets on the page.
11. Deprecations page leaves migration deadlines open-ended (significant)
Location: /gemini-api/docs/deprecations
Problem: Many rows say "No shutdown date announced," including gemini-3.5-flash itself (the recommended migration target for gemini-3-flash-preview, gemini-2.5-flash, and others). Conversely, gemini-2.5-flash is announced as shutting down October 16, 2026 — five months out — a real production deadline that is not surfaced on the changelog, models index, or home page. Veo rows just say "Coming soon" instead of dates.
Consequence: Teams using gemini-2.5-flash in production have a ~5-month migration window and no in-product nudge. Teams trying to plan migrations away from preview models toward gemini-3.5-flash cannot tell when 3.5 Flash itself will move. "Coming soon" Veo dates are unplannable.
The fix: Convert every "No shutdown date announced" entry into either a date or a documented policy ("≥12 months from GA date"). Replace "Coming soon" with a target month. Surface the October 16, 2026 Gemini 2.5 shutdown on the models index and the home page.
12. API-key page does not describe fallback behavior when no key is set (significant)
Location: /gemini-api/docs/api-key
Problem: The page says: "if both GEMINI_API_KEY and GOOGLE_API_KEY are set, GOOGLE_API_KEY takes precedence." It does not state what happens when neither is set — does the SDK error, fall back to Application Default Credentials, or something else? The page also says "REST API, or JavaScript on the browser, you will need to provide the API key explicitly," but the quickstart's JS sample initializes new GoogleGenAI({}) with no apiKey, which only works when an env var is picked up server-side — readers using the same snippet in a browser will fail silently.
Consequence: Server apps with both vars set silently use the wrong key, then troubleshoot the wrong system. Browser apps using the quickstart JS snippet ship with no key and fail at first call. Agents generating Node vs browser code cannot tell which init form to use.
The fix: Add a "key resolution order" subsection covering: both vars set, one var set, neither var set (state the actual error or fallback). Update the quickstart JS snippet to show new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }) and add a browser-specific variant that passes the key explicitly.
13. Text-generation Go sample won't compile (significant)
Location: /gemini-api/docs/text-generation
Problem: The Go snippet imports "os" but never uses it (Go compile error: imported and not used). It calls log.Fatal(err) without importing "log". It then discards the next err via _ despite the prior if err != nil pattern just above.
Consequence: Copy-paste from this canonical "first hello world" page produces code that doesn't build. The very next page (/thinking) imports "log" correctly in its Go snippet, so a developer who copies both still has to manually reconcile. Coding agents emitting Go code from this page will produce non-building suggestions.
The fix: Remove the unused "os" import, add the missing "log" import, and standardize error handling across all Go snippets on the site.
14. Text-generation Apps Script "hello world" has an inverted grammar (minor)
Location: /gemini-api/docs/text-generation
Problem: The Apps Script payload reads text: 'How AI does work?' while every other language sample on the same page sends 'How does AI work?'. The string is what gets sent to the model, but it also reads as a typo in a flagship example.
Consequence: A reader who runs the snippet sees a question they don't recognize as the one in the surrounding code. Not a functional bug, but it appears in the most-copied snippet on the page.
The fix: Change 'How AI does work?' to 'How does AI work?' so all five language samples send the same prompt.
15. Thinking page prints three different "thoughts summary" labels across SDKs (minor)
Location: /gemini-api/docs/thinking
Problem: The thought-summary print statements differ across languages on the same page: Python logs "Thought summary:" (singular), JavaScript logs "Thoughts summary:" (plural), Go logs "Thoughts Summary:" (plural + title case).
Consequence: Apps that copy these snippets into multilingual codebases ship inconsistent UX. Agents that synthesize a "show me the thought" feature from this page may pick any of three forms.
The fix: Pick one canonical label (e.g. "Thought summary:") and apply it across Python, JavaScript, and Go samples.
16. JavaScript snippets disagree on await main() vs main() across pages (minor)
Location: /gemini-api/docs/quickstart, /gemini-api/docs/text-generation, /gemini-api/docs
Problem: The quickstart's JS sample ends with main(); (synchronous call, top-level await not used). The text-generation page and the home page end the equivalent sample with await main();. Both use the same SDK init. Top-level await is only valid in ESM/REPL contexts; calling main(); without awaiting drops any error rejection.
Consequence: Readers copying the quickstart into a Node ESM module get a working program with silently-dropped errors. Readers copying the text-generation page into a CommonJS file get a syntax error on await. Neither page calls out the difference.
The fix: Pick one form per environment (e.g. always await main(); with an ESM note) and apply across all JS samples on the site.
17. File Search page only documents the polling pattern the changelog deprecated (significant)
Location: /gemini-api/docs/file-search
Problem: Both Python and JavaScript samples on the File Search page wait for the upload operation by polling: while not operation.done: time.sleep(5); operation = client.operations.get(operation). The changelog entry dated May 4, 2026 says: "Launched event-driven Webhooks support in the Gemini API to replace polling workflows for the Batch API and long-running operations." The file-search page does not mention webhooks or link to that migration.
Consequence: Developers writing new code from this page implement the pattern Google now considers superseded. Agents emitting upload code from this page produce blocking, less-efficient implementations by default.
The fix: Add a webhook-based variant alongside the polling sample, or replace the polling sample outright and link the May 4, 2026 changelog entry. Note when polling is still appropriate (e.g. quickstarts).
18. Billing page buries a production-down failure mode in prose (significant)
Location: /gemini-api/docs/billing
Problem: The Prepay plan description includes the sentence: "When your Prepay credit balance on the billing account hits $0, all API keys in all projects linked to that billing account will stop working simultaneously." This is the single most consequential operational fact on the page — total outage scope, no per-project isolation — and it sits inline in a paragraph with no callout, alert box, or cross-link from the troubleshooting or API-key pages.
Consequence: Operators discover the "one balance, all projects" coupling only after a coincidental outage across unrelated workloads. The troubleshooting page's 403/429 rows offer no hint that a zero balance is even a possible cause.
The fix: Promote this sentence to a warning callout on the billing page. Add a row to the troubleshooting backend-error table that maps the canonical 4xx returned when prepay hits $0 to "billing account balance exhausted." Cross-link the API-key page.
19. Pricing page mixes "prompts per month" with "requests per month" for the same allotment (significant)
Location: /gemini-api/docs/pricing
Problem: Gemini 3.5 Flash Standard rows say "Grounding with Google Search — 5,000 prompts per month (free, shared across Gemini 3)." The Batch row for the same model says "5,000 requests per month (free, shared across Gemini 3)." Same allotment, two terms. The image-output pricing also describes the same cost twice — as $60.00 per 1M tokens AND as $0.045 per 0.5K image — leaving readers to do the unit conversion themselves.
Consequence: Developers building monthly cost estimates against the wrong unit either over- or under-budget grounded search by an unknown multiple. Image-output budgets are equally ambiguous when the same SKU is priced in two different units side by side.
The fix: Standardize on one term ("requests" is canonical for billing) across Standard, Batch, Flex, and Priority. For image output, lead with the per-image rate and show the token equivalence as a footnote, not a parallel headline.
20. Safety-settings page omits parts of the HarmCategory enum and has a typo in normative guidance (minor)
Location: /gemini-api/docs/safety-settings
Problem: The page describes four HarmCategory values (Harassment, Hate speech, Sexually explicit, Dangerous) without saying whether this is the complete set or a configurable subset; the prose ("you can adjust these settings across four filter categories") implies it is the complete adjustable list, but does not cross-link to the enum in the REST schema for verification. The guidance paragraph also says "you should only adjust these settings if consistently is required for your application" — likely a typo for "consistency."
Consequence: Developers building moderation that needs categories beyond the four shown cannot tell whether other categories exist as adjustable filters. The typo undermines a normative sentence on a policy page.
The fix: State explicitly whether the four categories are the entire adjustable enum, and link to the canonical HarmCategory enum in the REST reference. Fix the "consistently" → "consistency" typo.
21. Grounding page requires you to render a widget "to satisfy ToS" but doesn't link the ToS (significant)
Location: /gemini-api/docs/grounding
Problem: The Grounding documentation says searchEntryPoint.renderedContent contains "the HTML and CSS to render the required Search Suggestions. Full usage requirements are detailed in the Terms of Service." No URL or section anchor is provided. The example groundingChunks[].web.uri values are also masked Vertex redirect URLs (https://vertexaisearch.cloud.google.com.....) rather than publisher domains, so readers cannot tell whether their citation surface will show the original publisher's domain or a Google-owned redirect host.
Consequence: Developers implementing grounded search cannot easily verify ToS compliance — a legally relevant requirement — without searching for the right ToS document themselves. Citation UX is built against the wrong assumption about what uri will actually be.
The fix: Link the specific ToS section that mandates rendering. Document the redirect-URL shape (what the host is, when/whether it ever resolves to a publisher URL) so customers can design citation UI correctly.
22. Live API overview ships zero code for a flagship feature (significant)
Location: /gemini-api/docs/live
Problem: The Live API overview lists three implementation paths (Server-to-server, Client-to-server, ADK) and a technical-specs table with bare codec parameters ("16-bit PCM audio, 16kHz, little-endian") but contains no code samples. The WebSocket spec mentions input/output sample rates but doesn't link to any reference WAV header, JSON message schema, or auth-token shape.
Consequence: Developers and agents arriving here cannot estimate effort or pick a path without three additional clickthroughs, and once they land on a sub-page they have no shared mental model to compare against. The PCM specs without a reference make it easy to ship audio at the wrong sample rate.
The fix: Add a minimal "Hello, Live" snippet in Python (server-to-server) at the top of the overview, plus a one-line WebSocket auth message example. Link the PCM spec to a canonical sample WAV or codec reference.
23. No OpenAPI/Discovery document linked from the REST reference (significant)
Location: Site-wide; /api/rest
Problem: The REST reference lists endpoints by name (generateContent, streamGenerateContent, batchGenerateContent, embedContent, CreateInteraction) without an attached machine-readable OpenAPI/Discovery document URL. The "Interactions" endpoint is even marked "Recommended" without a path. There is also no llms.txt / llms-full.txt index referenced anywhere in the scraped pages.
Consequence: AI coding agents (Claude Code, Cursor, Copilot) consuming the Gemini docs must scrape HTML and infer request shapes from prose examples — many of which (see issues 5, 6, 7, 13) are inconsistent or broken. There is no canonical machine-parseable contract to fall back on.
The fix: Link the existing Generative Language API Discovery / OpenAPI document prominently from /api/rest, give the "Interactions" endpoint a concrete URL, and optionally publish llms.txt / llms-full.txt indexes at the docs root.
What they do well
- Comprehensive changelog with dated entries and explicit "breaking change" labels makes it possible to reconstruct migration timelines (even when the rest of the docs lag the changelog by weeks).
- OpenAI-compatibility layer is a low-friction onboarding path and shows reasoning-effort ↔ thinking-level mappings explicitly.
- Quickstart paths exist for five languages (Python, JS, Go, Java, Apps Script) — broader than most competitor SDKs.
Top 3 recommendations
- Reconcile Gemini 3 model identity across home, models index, pricing, and deprecations pages — populate the empty
## Gemini 3section, pick one canonical name per capability tile, and audit every code sample'smodel=against the deprecations table. - Fix the date-decay across the site — past-tense the May 7 dormant-key block, surface the June 19 unrestricted-key cutoff in places people actually read, move shut-down models out of "upcoming" tables, and replace
gemini-3-pro-previewreferences with their successor IDs. - Fix the broken code samples that block copy-paste — structured-output Go (issue 5), OpenAI-compat Python double-nest (issue 6), REST JSON examples (issue 7), Go text-gen imports (issue 13), and the polling pattern superseded by webhooks (issue 17). Each silently breaks agents and produces wrong-behavior bugs rather than clean errors.