Skip to content

Router.Africa — Developer API Docs Scope

Backlog item #10. What the customer-facing API documentation must cover, where it lives, and what it depends on. This is the scope of the docs, not the docs themselves. Everything here restates decisions from ../architecture/decisions-log.md; where they disagree, the decisions log wins.

Audience: a developer who already uses the OpenAI or Anthropic SDK and wants to move over in minutes. The website promises “change one line” (website-copy.md), so the docs have to make that true and be honest about where we differ.

Surface documented: api.router.africa, the external API served by apps/api. Not the dashboard API, not the admin API.


  • One line to switch. The first page a developer sees shows the base URL and key change for the OpenAI SDK, the Anthropic SDK and plain curl. Working example before any explanation.
  • Document differences, not the whole OpenAI spec. Link to the upstream reference for request fields we pass through unchanged. Spend our own pages on what is ours: auth, credits, errors, extensions, models and rates.
  • Credits wording rule applies. Credits are never money in the docs: no “wallet”, “cash”, currency symbols or refund language on balances (build inventory → Wording rule). Currency appears only where the top-up payment is described.
  • Accurate over complete. A behaviour is documented only once it is built and verified. Items still marked “Verify” in openrouter-api-comparison.md (Responses format, finish_reason normalisation) are documented as supported only after they are confirmed.
  • Written by hand, fully curated. No generated reference, no spec-driven pages. The API can expose far more endpoints than we choose to show, so what is documented is a deliberate editorial decision, page by page. Documented means supported: an endpoint or parameter that has no page is not part of the public contract, even if it works. Adding one to the docs is an explicit act, not a side effect of shipping a route.
Section Covers Source of truth
Quickstart Sign up, get a key, first request in curl, OpenAI SDK (Python, TypeScript) and Anthropic SDK. Streaming example dashboard-scope.md onboarding flow; the same curl as the dashboard Overview
Authentication Authorization: Bearer key, key format and prefix, shown once, HTTPS only, never put keys in client-side code. Other header forms only if confirmed to reach Bifrost’s VK layer (comparison #6) Decisions log → API key security model
Endpoints Chat completions (streaming and not), models list, plus whichever of Responses, Anthropic Messages, and the customer-callable key-info and generation-lookup endpoints we commit to build (comparison #2, #9, #10) Hand-written reference pages, checked against the built route
Models and rates How to list models, what “model” strings look like, that a model needs an enabled key and a published rate, deprecation policy. Deferred: rates and models docs, and any public rates page, come back later pricing-model.mdModel availability; decisions log → v1 model list
Credits and billing What a credit is, how a request is charged (Bifrost-reported tokens × the published rate, locked at hold time), holds and what a customer sees when a hold is placed and released, low-balance behaviour, top-up with fee shown before payment. No refunds or cash language Decisions log → Charge basis, Credit balance & non-refundability, Top-up fee; design-doc.md §5
Errors Full table: status, error code, meaning, whether to retry. Must include insufficient credits, key revoked/expired/over its spend cap, model not allowed or not enabled, 409 for an in-flight duplicate, 429 rate limited, upstream failure and timeout. Error body shape backend-scope.md §3 and §6; comparison 3.4
Rate limits That limits exist per key, the 429 behaviour and Retry-After if we send it, backoff guidance. Limits are set per org in Admin and not shown to customers, so the docs describe behaviour, not numbers Decisions log → Rate limiting; build inventory → Rate limits
Idempotency and retries Automatic short-window duplicate protection, the optional Idempotency-Key header as a Router.Africa extension (with an extra_headers example for the OpenAI SDK), safe retry rules Decisions log → Idempotency key design (names this docs item explicitly)
Streaming SSE format, final usage chunk, what is charged if the client disconnects mid-stream (settled on Bifrost-reported partial usage) Decisions log → Mid-stream client disconnect policy
Spend caps and key scoping Per-key model allowlist, spend cap in credits with reset period, expiry; what error a capped key returns Build inventory → Features
Data and privacy Prompts and responses are saved by default with per-workspace opt-out, who can read them, that headers and keys are never stored. Must match the terms and privacy policy wording Decisions log → Audit trail & prompt/response retention; backlog #17
Compatibility notes What differs from OpenAI and Anthropic: unsupported parameters, no batch endpoint, no :free/:nitro-style variants, no model aliases, no session-sticky routing until built Comparison 3.1, 3.2 (Diverge rows); decisions log → Batch/async endpoint
Changelog and status Dated API changes, deprecation notices. Link to the status page (at launch, decided) New

Which endpoints appear is a curated list, kept as its own short table in the docs repo (endpoint, status: public / hidden, notes). The proposed launch list and reasoning are in api-surface.md.

Out of scope for the docs: dashboard usage help (a separate help surface, if any), admin app, internal architecture, Niobi payment mechanics beyond what a customer sees, provider names and per-provider behaviour.

The docs can’t be finished before these are settled. Drafting can start on the parts marked ready.

Needs Status Affects
Backend scope (#4) Done Errors, request flow, streaming, idempotency: ready to draft
OpenRouter comparison (#1) Done Compatibility notes: ready to draft
Pricing model (#11) Done Credits, models and rates: ready to draft
Error catalogue: exact status codes, error codes, body shape Not defined; to be defined before the apps/api build (decided) Errors page. Treat as a contract
Which extra endpoints are public at launch (Responses, Messages, key-info, generation lookup) Proposed in api-surface.md, to confirm Endpoints section, compatibility notes
Rate-limit response contract (Retry-After, x-ratelimit-*) Not defined; before the build (decided) Rate limits page
Schema (#6) Next up Field names in any endpoint that returns ledger or key data
Bifrost verifications in backlog #18 Open Auth header forms, models list

Decided (2026-09-20):

  • Hand-written and curated, hosted at router.africa/docs. No new origin: the four-origin split in the decisions log is unchanged, and the docs are static with no auth and no CORS.
  • Source lives in the website repo (router.africa-website, Astro), not the monorepo. The docs are site content and deploy with the site.
  • Tooling: Astro Starlight, added to the existing website project. It provides the sidebar, search (Pagefind), per-page table of contents, code blocks with copy button, and tabs for curl / Python / TypeScript (tabs need MDX, which Starlight brings in). Docs pages are written as Markdown or MDX under Starlight’s docs content collection, so they sit alongside the blog collection in src/content.config.ts. Starlight’s own layout serves /docs, so it needs theming to match the site (colours, fonts, logo) rather than reusing BaseLayout.
  • Things to check in a short spike before building the docs:
    • Path: Starlight serves from the root of its collection, so files go under src/content/docs/docs/ (or the equivalent) to land at router.africa/docs.
    • i18n clash: the site has Astro i18n set up for en / fr / sw. Starlight has its own locale settings. Confirm the two coexist, with docs English only and the site’s other routes unchanged.
    • Sitemap: the site already uses @astrojs/sitemap. Confirm no duplicate integration or double entries, and keep /internal/ filtered.
    • Adapter: confirm Starlight builds and serves correctly with @astrojs/cloudflare.
  • Drift between apps/api and the docs: no process for now. Revisit later if it becomes a problem.
Question Approach
Code samples curl, Python and TypeScript for every documented endpoint, written by hand
Versioning The API is /v1. Breaking changes need a new version; the changelog records everything else
Languages The site is en / fr / sw. Docs are English only at launch unless decided otherwise (section 6). Starlight has its own i18n, so translating later is possible
  • Dashboard: the Overview quickstart curl (screen 8) and the key reveal sample curl (screen 6) should be the same snippet as the docs quickstart. A “Docs” link in the dashboard shell and an API reference link on the Rates screen. Small additions to build-inventory.md.
  • Website: this is website-repo work: adding Starlight, theming it to match the site, a nav link, and a link from the “change one line” section once the docs exist. Any claim in website-copy.md about compatibility must be matched by a page here.
  • Backend (apps/api): the error catalogue and rate-limit headers are build work, not just docs work: define them as a contract with the build. Add to the execution plan (#9).
  • CI/CD (#13): nothing new; the docs deploy with the website.
  • Content logging (#17): the Data and privacy page is a fourth place the default-on disclosure must appear, next to signup, terms and privacy.

Decided (2026-09-20):

  • The error catalogue and rate-limit response headers are defined before the apps/api build.
  • A status page ships at launch (tooling and location to be chosen).
  • The public rates page and the models/rates docs are deferred; they need more supporting content and come back later.

In progress: the launch endpoint list is analysed in api-surface.md (proposed, for confirmation).

Open:

  1. Confirm the launch endpoint list in api-surface.md.
  2. Docs language: English only at launch is assumed (the site is en / fr / sw). Say if fr and sw are needed.
  3. Error format: adopt OpenRouter’s or publish our own (api-surface.md §5).