gdelt-cloud-docs — Agent Guide
The Mintlify site behind docs.gdeltcloud.com. It lives inside thegdelt-cloud monorepo and
auto-deploys on push to main.
This file is internal. It is deliberately not in docs.json, so it is excluded from the built
site and from the llms.txt Mintlify generates from the nav — a crawling model should read the
product, not our authoring conventions.
★ The spec and the reference tier are GENERATED — never hand-edit them
They come from the contract registry at
nextjs_/lib/api/v2/registry/ — the same objects the server
imports at request time to build its param allowlist and validate enums. That is what makes them
trustworthy: a generated page cannot describe a value the API rejects, or omit one it accepts.
To change one, edit the descriptor and run pnpm gen:contract in nextjs_/. prebuild runs
the gate, so a hand-edit fails the Vercel deploy with the fix command in the error.
Hand-write prose pages only. The emitter owns numbers and tables; humans own sentences.
Never restate a value list in a hand-written page
Not because duplication is untidy — because it drifts, and drifted docs are worse than absent ones. Measured on 2026-08-05 against a running server, hand-written pages claimed:categoryis “an open vocabulary” that “also accepts CAMEO+ code strings” —category=TE01returns400 INVALID_CATEGORY.- story categories are “not a fixed enum” with ten prose theme buckets — the real vocabulary is 11 closed snake_case values, and a display label 400s.
- CAMEO+ has 8 domains — it has 10;
CRIMEandDEMOGRAPHICboth work and were undiscoverable. - coverage starts January 2025 — that month holds 11 events. Usable coverage starts March 2026 (15,744 events). True, and a lie.
/reference/enums instead. It is generated, and it carries the real rejection code per
vocabulary (INVALID_ENUM, INVALID_CATEGORY, INVALID_REGION, INVALID_CONTINENT — they differ).
Open vocabularies are not enums
reference/enums.mdx renders three value-spaces in visibly different language, and the difference is
load-bearing: closed (“the authoritative set; anything else 400s”), observed (“a dated
MEASUREMENT; the API accepts values outside this list”), identifier (“a key, not a list”).
The spec once declared a closed 13-value form_type enum against a corpus holding 264, where
424B2 alone was 21% of a 30-day window — wrong in both directions with a generator’s authority
behind it. Never describe an observed vocabulary as though it were closed.
Mintlify gotchas that cost real time
- Inline
{ "openapi": "GET /path" }refs only resolve when the spec is declared at the tab or group level. A globalapi.openapiarray is not enough — without the tab/group declaration every inline ref silently generates nothing. We declare it at the tab level and on each group holding inline refs. - Generated page slugs come from the operation’s OpenAPI
tags, not the nav group name. An op taggedEntitieslands at/api-reference/entities/...wherever you place it. So tag and group names must avoid&and other URL-hostile characters — an&breaks slug generation and the pages silently disappear. Use “and”. - Only top-level groups always expand; nested groups honour
"expanded": false. - A page not in
docs.jsonis not built. An.mdxon disk with no nav entry is invisible, and a spec operation with no nav entry returns 200 at its slug while nothing links to it — five had accumulated that way, including three Atlas endpointsindex.mdxtells readers to call. Guarded now bynextjs_/tests/docs/contract-doctrine.test.ts, both for operations and for generated MDX. mint devignoresPORT. It probes 3000, then 3001. Check which one it actually bound.
Before pushing
nextjs_/: npx vitest run tests/docs — the reachability, banner and honesty-label guards
all live there and ride the existing suite.

