Skip to content

OpenRouter for Africa — v1 Design Document

Status: Draft for internal review Owner: Hassan Last updated: 2026-09-19 (see note below)

Update 2026-09-19: reconciled against architecture/decisions-log.md (audit trail, key mapping, rate-limit ownership, pricing source of truth).

Companion document: see OpenRouter for Africa — Business Model & Pricing for cost economics, margin, and pricing strategy.

Developers and businesses in strategic African markets face real friction accessing frontier AI models: international card declines, unpredictable FX costs, and USD-denominated billing that doesn’t fit how businesses in these markets actually pay. Global aggregators (OpenRouter, Portkey, etc.) solve the “one API for many models” problem but not the payment friction problem.

Niobi already solves the payment friction problem across 16+ African markets — collections, wallets, local payment methods, local currency. This product combines Niobi’s payment rails with a model-routing API to give African developers frictionless, local-currency access to frontier and open-weight AI models.

The wedge is payments, not routing. The routing/gateway layer is a commodity we can stand up quickly using existing open-source tooling. The differentiation is entirely in how customers pay and get billed.

Goals:

  • Single OpenAI-compatible API endpoint giving customers access to frontier closed models (GPT, Claude, Gemini) and a broad catalog of open-weight models (DeepSeek, Qwen, Kimi, GLM, Llama, etc.)
  • Prepaid, local-currency billing built on Niobi’s existing collections infrastructure
  • Reseller model — we hold all provider relationships; customers never bring their own upstream API keys
  • Launch in 1–2 strategic markets first, not all 16 at once

Non-goals for v1:

  • No auto-routing/optimization logic (cheapest/fastest provider selection) — that’s a mature-stage feature
  • No self-hosted/fine-tuned model hosting
  • No enterprise features (SSO, RBAC) — target segment is developers/SMBs, not large enterprises. Audit trail is in scope for v1 (corrected 2026-09-19; see architecture/decisions-log.md).
  • No sub-merchant onboarding — we are the single merchant of record; all customer accounting happens in our own ledger, not in Niobi’s sub-merchant structure

Router.Africa architecture

Four layers, top to bottom:

  1. Customer — a developer or business calling our API, and viewing usage/balance on our dashboard.
  2. Niobi (existing infra) — payments and wallet rails. Customers top up via Niobi’s collection methods (mobile money, bank transfer, etc.) into a single pooled merchant wallet. Niobi confirms settlement via callback.
  3. Our product (built) — the layer we’re actually building:
    • Customer dashboard — balance, usage history, API key management
    • Billing ledger — the real source of truth for each customer’s credit balance; consumes Niobi payment confirmations and decrements balance as usage occurs
    • Auth & API keys — Router.Africa-issued API keys, mapped 1:1 to Bifrost virtual keys so rate limits and budgets are enforced at the gateway (updated 2026-09-19)
  4. Gateway (open-source, self-hosted) — Bifrost, chosen over LiteLLM and already deployed. Deployed by us, not built from scratch. Normalizes requests to one API and routes to upstream providers. Handles per-key rate limiting, spend tracking, and fallback.
  5. Providers (outsourced):
    • Direct relationships: OpenAI, Anthropic, Google — required for closed frontier models, no aggregator can resell these
    • One aggregator (Fireworks, primary candidate) — covers 200+ open-weight models including DeepSeek, Qwen, Kimi, GLM, Llama, hosted on US/EU infrastructure (avoids direct cross-border data residency questions with Chinese-hosted APIs)

This gives ~4 total provider relationships instead of hundreds of individual integrations. Provider selection rationale, cost comparison, and margin implications live in the companion business model document.

Model: single merchant wallet, not sub-merchants. All customer top-ups flow into one pooled Niobi wallet. Per-customer attribution happens entirely in our own ledger, not in Niobi’s account structure.

Inbound (payment confirmation):

  • Customer chooses the credit amount they want (e.g. 1,000). We add the Niobi transaction fee (configured in admin — see §5) and raise the collection request for the total (e.g. 1,040 if the fee is 40). The customer sees this breakdown — credits received, fee, total to pay — before confirming.
  • We tag the request with a unique reference (third_party_reference_1) — likely customer_id + a unique top-up identifier — so the callback can be matched back to the right customer unambiguously
  • Niobi sends a callback on final status (success, failure, or timeout) via our configured callback URL
  • Our billing ledger receives the callback, validates the signature, and credits the customer’s internal balance with the credit amount only, not the fee — only after confirmed success, never optimistically

Outbound (balance & reconciliation):

  • Periodic reconciliation: sum of all customer ledger balances should equal (pooled Niobi wallet balance) minus (funds already consumed via inference) minus (transaction fees collected). Fees are Router.Africa revenue, not customer balance, so they are recorded separately at top-up time. A mismatch signals a missed or duplicated callback.
  • get-account-balance and transaction status endpoints available for real-time checks and dispute investigation.

Idempotency is critical. The reference tagging convention must guarantee a callback can never be applied twice, even on retry or resend (Niobi supports manual callback resend from the portal).

Explicitly out of scope: Niobi’s disbursement/payout API — this product doesn’t disburse money to recipients, it only collects.

Open question for the payments team: confirm the callback and reference-tagging convention above is sufficient, and whether there’s any existing pattern internally for “collect funds, tag by internal customer ID” that this can reuse rather than building fresh.

  • Niobi wallet = aggregate float. Internal ledger = source of truth for per-customer balances.
  • Balances are held as credits, and credits are equivalent to tokens. The dashboard and API show a Credit balance (e.g. “Credit balance: 100”) and never attach a currency symbol or code to it, and any copy that mentions tokens must say credits. This is deliberate: a currency-labelled balance sets an expectation that unspent funds can be withdrawn or refunded. Credits are consumed by usage and are not redeemable for cash.
  • Top-ups. The customer pays credit amount + transaction fee through Niobi; the ledger credits exactly the credit amount (1 credit per 1 unit of the currency collected, no conversion needed since collection already happens in local currency). The fee is not credited. Example: top up 1,000 credits with a 40 fee → customer pays 1,040, receives 1,000 credits.
  • Transaction fee (the “Niobi markup”). Configured per vendor in the admin app, not hardcoded. The fee is shown to the customer before they pay and stored on the top-up record (credit amount, fee, total collected) for reconciliation and dispute handling.
  • On each inference request: gateway reports token usage; ledger looks up the current per-model price (the daily published rate — see pricing-model.md; the business model’s price table is illustrative only) and decrements the customer’s balance accordingly — priced at time of consumption, not at time of top-up.
  • This means repricing takes effect immediately and uniformly for every customer the moment the price table is updated — there’s no need to track which balance was funded under which price regime, no grandfathering, no dual-pricing logic. The balance is just credits; the price list determines what it buys today.
  • Balance checks must be atomic — concurrent requests against the same balance must not be able to overdraw it (race condition risk if check-then-charge isn’t handled at the ledger/transaction level).
  • Requests are blocked once balance hits zero — no postpaid credit extended, ever, given the reseller liability exposure.
  • Transparency requirement: the current price per model must be clearly visible on the dashboard before a customer spends, since their existing balance can buy more or less depending on when they use it relative to the last repricing.
  • Reseller liability: we inherit responsibility for enforcing upstream providers’ usage policies on our customers; ToS from each provider should be reviewed before launch.
  • Prepaid-only model substantially reduces (but doesn’t eliminate) credit risk — no postpaid exposure to non-payment.
  • Secrets management: upstream provider API keys live only on our gateway, never exposed to customers; use a secrets manager, not env files.
  • Abuse monitoring: basic usage/content monitoring needed to catch obvious ToS violations before a provider suspends our account.
  • Per-customer rate limiting at the gateway layer (Bifrost virtual key limits, configured from Postgres), to contain a compromised or malicious key.
  • Gateway software supply chain: track upstream Bifrost security advisories; pin versions deliberately rather than auto-updating.
  • Data handling: prompts and responses are stored by default; customers can opt out of us saving them. Encryption in transit/at rest for anything stored, with a clear retention policy (indefinite for now, to be revisited) — we are a data processor for customer traffic passing through to model providers. An audit trail of request metadata is kept regardless.