CLAUDE.md — flexaihq/docs
This is the FlexAI documentation site (Mintlify, published athttps://docs.flex.ai). Config is docs.json; content is .mdx under the section folders (getting-started/, core-services/, platform-services/, cli/, blueprints/, inference-api/, …).
Voice & tone
All published docs follow the house voice & tone guide at.github/VOICE-AND-TONE.md: capability-first framing, benefit-before-caveat, second person, confident-not-apologetic. Read it before writing or reviewing a page — tone work never changes a fact, command, limit, or URL.
changelog.mdx is the one exception, and it is a hard one. Entries are written like commit messages: heading as subject line, one bullet per change, one fact per bullet, numbers and ids over description, present tense and present state. No reassurance, no advice, no counts or framing, no background, nothing a linked page already carries — but no fact dropped either. The rule, with examples of what gets cut, is in the authoring note at the top of changelog.mdx; read it before adding an entry.
⚠️ inference-api/ is synced from flexaihq/token-service — prose round-trips, generated files don’t
The inference-api/ + snippets/inference-api/ trees are synced from flexaihq/token-service by its .github/workflows/sync-docs.yaml (the forward sync), which opens/updates the PR on branch auto/sync-token-service-docs. The source-of-truth is token-service/docs/content/.
Prose ROUND-TRIPS — safe to edit here, including in the Mintlify UI. Hand-written pages — overview.mdx, quickstart.mdx, guides/*.mdx, and reference/*.mdx except errors.mdx — are mirrored back to token-service/docs/content/ by reverse-sync-prose.yaml whenever they change on main. So a Mintlify edit committed to main publishes immediately and opens a reflect-back PR upstream (auto/sync-docs-prose) for engineers to review. docs/content/ stays canonical; the next forward sync is a no-op. (Publish-first: the Mintlify editor must be configured to commit to main.)
Generated files NEVER round-trip — never edit them anywhere:
inference-api/reference/errors.mdx— rendered byscripts/generate-docs.pyinference-api/openapi.yaml— copied fromtoken-service/docs/openapi.yamlsnippets/inference-api/billing-constants.mdx— generated from backend constants
guard-synced-docs.yaml fails any PR that touches the generated files above (prose PRs pass). To change generated content, edit the upstream source/generator in token-service. Full playbook: token-service/docs/authoring-inference-api-docs.md.
- There is no model catalog page — the public model list lives at https://flex.ai/models (the old
/inference-api/reference/modelsURL redirects there viadocs.json).
⚠️ Two different hosts — the API is api.flex.ai, the browser app is platform.flex.ai
Getting these the wrong way round is the easiest mistake to make on this site.
The reason the split is strict is that
api.flex.ai serves /v1/* only. Everything
else on that host — /, /dashboard, /signup, /api/* — is rejected at the edge with
a bare 404 before it reaches any backend. So a dashboard link or an /api/* path pointed
at api.flex.ai is not merely unconventional, it is a dead link.
The trap runs the other way too, and that direction is worse, because it does not look
like a failure. platform.flex.ai routes /api/* plus the single exact path
/v1/models. Every other /v1 path falls through to the browser app: a GET returns
200 with an HTML page, and a POST returns 405, also HTML. An SDK pointed at
https://platform.flex.ai/v1 is handed a web page instead of an error, so it fails
somewhere further down with a confusing message. This is exactly why probing one endpoint
is never enough to call a host an API base. Never write platform.flex.ai/v1 in a
snippet.
tokens.flex.ai is the original host and is being retired. Engineering owns that
retirement and its cutover; until then tokens.flex.ai/v1/* still serves the identical
API surface, and its browser shell redirects to platform.flex.ai. Nothing new should be
built on it: point API examples at api.flex.ai and dashboard or /api/* links at
platform.flex.ai, and never rewrite a dashboard link to api.flex.ai. A customer still
calling tokens.flex.ai/v1 should move their base URL to https://api.flex.ai/v1; don’t
promise a retirement date. As of PRO-101 the name is no longer used anywhere in
customer-facing docs.
The OpenAPI servers: list carries exactly https://api.flex.ai and
https://eu.api.flex.ai, in that order, which is what makes generated SDKs and “Try it”
default to the canonical host.
Retired browser hosts. console.flex.ai (301s to platform.flex.ai, path preserved)
and auth.flex.ai (/ui/login, /ui/recovery, /registration) are superseded by
platform.flex.ai/login, /recovery and /signup. They still resolve, so a stale link
is a consistency problem rather than a broken one, but do not write new ones.
⚠️ Never reference staging
These are customer-facing docs. The internal non-prod surfaces —tokens.flexsystems.ai, tokens.staging.flex.ai, and tokens.dev.flex.ai (the staging and dev hosts after the flexsystems.ai retirement, ENG-1538) — must never appear in any published page: no base URLs, examples, links, or OpenAPI servers. The CI guards reject all three.
- This applies site-wide (every published
.mdxandinference-api/openapi.yaml), not just the Token Factory (Inference API) tab. - For
inference-api/**content, the canonical home is upstream inflexaihq/token-service(docs/content/,docs/openapi.yaml, or the generator). Generated files edited here are overwritten by the sync; prose edits round-trip upstream — so never introduce a staging URL either way. Token-service’ssync-docs.yamlguard blocks a staging URL from reaching the synced payload, andreverse-sync-prose.yamlre-checks prose on the way back. no-staging-refs.yamlis the receiver-side backstop: it fails any PR (and push tomain) whose published content containstokens.flexsystems.ai.
docs.json (navigation) IS owned here
The nav is not synced — it lives only in this repo. So:
- Adding/removing/reordering an Inference API page (e.g. a new guide) is a manual edit to
docs.jsonhere, paired with the page existing upstream (the sync delivers the.mdx,docs.jsonmakes it appear). - When a page is withdrawn upstream, the sync deletes the
.mdxbut leaves itsdocs.jsonentry, and Mintlify still builds and serves a 404.nav-integrity.yamlfails any PR — the sync PR included — whosedocs.jsonlists a missing page, so auto-merge holds the sync and fails its own run. Drop the entry in a separate PR tomain; once it lands, auto-merge updates the sync branch and merges it. For a rename, drop the old entry first and add the new one after the sync lands (the check rejects an entry whose file isn’t onmainyet). Leave the sync PR itself alone: a comment, review or manual branch update makes auto-merge hold it for a human. - The Token Factory tab (the Inference API) is the primary tab;
Platformis second. Itsopenapikey points atinference-api/openapi.yaml.
Everything else
All other sections (platform, core-services, cli, blueprints, console, faq, best-practices, …) are authored directly in this repo — edit the .mdx here normally. Only the inference-api/ + snippets/inference-api/ trees are externally owned.