Router.Africa — Public API Surface
Which endpoints exist at OpenRouter, which we will have, and which we make public (documented, therefore supported) at launch. Input to api-docs-scope.md (backlog #10). Built from openrouter-api-comparison.md §1, §3 and §4, checked against the decisions log, build-inventory.md and website-copy.md.
Status: proposed, for confirmation. Rows marked Public are what the docs will cover. Anything not public may still exist internally; documented means supported (see api-docs-scope.md §1).
Legend. Ours = whether we will have it at all: Yes, Verify (depends on Bifrost support, backlog #18), Build (custom code in apps/api), No. Public at launch: Yes, Later, No.
1. Inference endpoints (api.router.africa, API-key auth)
Section titled “1. Inference endpoints (api.router.africa, API-key auth)”| OpenRouter | Ours | Public at launch | Reasoning |
|---|---|---|---|
POST /chat/completions |
Yes | Yes | The core product. Comparison #1 |
POST /messages (Anthropic format) |
Verify | Yes, once verified | website-copy.md already tells developers the Anthropic SDK works with a one-line change, so this is a public promise. Bifrost’s /anthropic prefix should cover it; confirm Anthropic-native bodies work end to end (comparison §5). If it fails verification, the website copy must change instead. Path is ours to define (e.g. /v1/messages) |
POST /responses (OpenAI Responses) |
Verify | Later unless verified | What Codex and the Agents SDK speak. Bifrost support is unclear (comparison #2). Don’t document until it works; not promised anywhere yet |
GET /models |
Yes (key-scoped: Bifrost’s list is VK-aware) | Yes | Needed by every SDK and by developers picking a model. Fields and any pricing in it are deferred with the rates decision (section 4) |
GET /models/user |
No | No | Same job as a key-scoped /models. No separate endpoint |
/embeddings |
Not at launch | Later | Token-priced, so the easiest addition later, but the model catalog and pricing model are built around chat token types. Add with its own rates |
/rerank, /images, /videos, /audio/speech, /audio/transcriptions |
No | No | Non-token billing dimensions (images, seconds, characters) with no pricing model behind them (pricing-model.md covers token types) |
/api/alpha/decisions |
No | No | Alpha at OpenRouter; not relevant |
2. Key, usage and lookup endpoints
Section titled “2. Key, usage and lookup endpoints”| OpenRouter | Ours | Public at launch | Reasoning |
|---|---|---|---|
GET /key (limit, remaining, usage, expiry) |
Build | Yes | Comparison #9: customer-callable balance and usage is table stakes for a prepaid product. Returns the key’s spend cap and usage, expiry, and the workspace’s credit balance, all in credits (wording rule). Exact fields are part of the schema and contract work |
GET /generation?id= (cost, latency, attempts) |
Build | Later | Serves dispute investigation (comparison #10), but the dashboard’s Log detail drawer already covers it for customers. The response must still carry a request id so support and customers can refer to a request |
GET /generation/content?id= |
No | No, by decision | Stored prompts and responses are readable only by admins and every read is audited (decisions log → Audit trail & prompt/response retention). An API key is not an admin, so this would break that rule |
POST /generation/feedback |
No | No | Nice to have; not needed |
POST /oauth/token (workload identity) |
No | No | Explicit v1 non-goal (comparison #13) |
3. Management surface (keys, workspaces, guardrails and so on)
Section titled “3. Management surface (keys, workspaces, guardrails and so on)”All of OpenRouter’s management endpoints (/keys, /workspaces, /guardrails, /byok, /presets, /organization/members, /scim/*, /observability/destinations, /analytics/*, /activity, /files, /containers) are not public at launch.
Our equivalents are the dashboard’s own routes on app.router.africa (apps/dashboard-api, Better Auth session, CORS scoped to the dashboard). They are not an API-key surface and are not in the build inventory as one. Webhooks are already on the “Later” list.
Likely first additions later, if customers ask: a keys provisioning API (for resellers creating keys per end user), then usage and activity queries. BYOK, SCIM and observability destinations are excluded by earlier decisions (no BYOK; SCIM irrelevant to v1).
4. Request and response extensions to document
Section titled “4. Request and response extensions to document”| Item | Ours | Documented at launch | Notes |
|---|---|---|---|
Idempotency-Key request header |
Yes (decided) | Yes | Router.Africa extension; the decisions log already names the developer docs as where it is explained |
| Request id on every response | Build | Yes | Needed to refer to a request in support; also enables /generation later |
usage with token counts |
Yes | Yes | Standard |
| Cost / remaining balance in the response body (comparison #27) | Verify → Build | Decide | Highest-value addition in the comparison, but not yet decided for our credits model. Whether Bifrost returns cost in the body is a verification item. If added, in credits |
models[] as an alias for fallbacks (comparison #16) |
Build (thin) | Later | Not needed at launch: fallback chains are configured by staff, not per request |
session_id sticky routing (comparison #17) |
Build | Later | A cost optimisation, not a launch feature |
provider, plugins, route, :nitro / :floor variants, ~alias models, auto / pareto / fusion routers |
No | Listed as unsupported | Deliberate divergences (comparison #4, #19–21). The Compatibility notes page says so, so ported code fails predictably |
Rate-limit response headers (Retry-After, x-ratelimit-*) |
Build | Yes | Contract to define with the apps/api build (decided, section 5) |
| Error format and error types | Build | Yes | See section 5 |
5. Decisions recorded (2026-09-20)
Section titled “5. Decisions recorded (2026-09-20)”- Error catalogue and rate-limit headers are defined before the
apps/apibuild, as a contract the docs depend on. The main choice inside it (comparison #39, #40): adopt OpenRouter’serror.metadata.error_typevocabulary and{error: {code, message, metadata}}envelope so ported client code keeps working, or publish our own. Still to decide; recommend adopting OpenRouter’s shape and a smaller subset of its 27 types that we can actually emit. - Status page at launch: yes. Tooling and where it lives are to be chosen.
- Public rates page and the pricing fields in
/models: deferred. Rates and models need more supporting content than fits now; revisit later.
6. To confirm
Section titled “6. To confirm”- The launch list: Chat completions, Messages (once verified), models list, key info (
GET /key); Responses only if it passes verification. - Whether cost and remaining balance appear in the response body at launch (section 4).
- Error format: adopt OpenRouter’s, or our own (section 5).
- Whether
GET /generation(without content) should be public at launch rather than later, if customers need to look up a request programmatically. - Verification items that gate this list, from backlog #18 and comparison §5: Anthropic-native bodies on
/anthropic, Responses support, cost in the response body,Authorization: Bearerreaching the VK layer.