BYOK API

Architecture

BYOK API uses an iframe bridge pattern to enable secure cross-domain AI access. This page explains how the pieces fit together.

The problem

Web apps that want to use AI need API keys. Today there are three bad options:

  1. Backend proxy — app developer holds your keys on their server. Trust issue, cost markup, vendor lock-in.
  2. Client-side keys — paste your key into the app. Any JS on the page can steal it. XSS = game over.
  3. OAuth-style delegation — a central server issues tokens. Adds a middleman, requires infrastructure, keys still live server-side.

The solution: an AI key wallet

BYOK API works like MetaMask — your API keys live in your browser, in a wallet on a separate origin:

┌─────────────────────┐     postMessage/RPC     ┌─────────────────────┐
│   Consumer App      │ ◄──────────────────────► │   Bridge (iframe)   │
│   (any-app.com)     │                          │   (byokapi.com)     │
│                     │                          │                     │
│  ByokClient         │                          │  API Keys (IndexedDB)│
│  TransportModel     │                          │  Grant Records       │
│  AI SDK v6          │                          │  Provider Routing    │
└─────────────────────┘                          └─────────┬───────────┘

                                                    HTTPS API calls

                                              ┌────────────┼────────────┐
                                              │            │            │
                                         OpenAI      Anthropic    OpenRouter

Key properties

  1. Cross-origin isolation — the wallet (bridge) runs on a different origin, so the app cannot read its IndexedDB or localStorage. Same security model as MetaMask's extension isolation.
  2. postMessage RPC — communication uses kkrpc, a typed bidirectional RPC library over postMessage — like window.ethereum but for AI calls.
  3. Consent popup — grant requests open a popup on the wallet origin where the user approves capabilities — like MetaMask's transaction approval dialog.
  4. No backend required — the entire flow happens in the browser; API calls go directly from the wallet to providers. No auth server, no middleman.

Communication flow

  1. Consumer app creates a ByokClient and calls connect()
  2. Client creates a hidden <iframe> pointing to the bridge's /bridge page
  3. IframeParentIO (kkrpc) is initialized before setting iframe.src to avoid missing the init signal
  4. The bridge's iframe page creates an IframeChildIO and exposes the BridgeAPI
  5. Client calls handshake() to register and check for existing grants
  6. Client calls requestGrant() which triggers a consent popup on the bridge origin
  7. Once granted, the client gets TransportLanguageModel instances that proxy AI calls through the bridge

kkrpc details

The RPC layer has an important constraint: callbacks must be top-level function arguments, not nested in objects.

// Correct — callback is a top-level arg
api.streamLanguage(params, onChunk)

// Wrong — kkrpc can't serialize nested callbacks
api.streamLanguage({ ...params, onChunk })

This is because kkrpc serializes top-level function args as __callback__<id> placeholders that get wired up on the other side.

Provider routing

The bridge supports multiple AI providers:

  • OpenAI — direct API calls (language, image, TTS, STT)
  • Anthropic — proxied through the bridge's Next.js API route (CORS workaround)
  • OpenRouter — OpenAI-compatible API for hundreds of models
  • WASM/WebLLM — local models running entirely in the browser

The bridge reads the model ID, determines the appropriate provider, and routes the request accordingly.

On this page