OAuth PKCE

Third-party OAuth app registration and PKCE authorization flows.

Overview

BrainstormRouter supports OAuth 2.0 with PKCE (S256 required) for third-party integrations. The token exchange produces a standard BrainstormRouter API key (br_live_*) scoped to the authorizing user's tenant. The issued key works with all existing middleware -- rate limits, budgets, guardrails, and memory.

Developer endpoints (API Key auth)

MethodPathDescription
POST/v1/oauth/appsRegister an OAuth app
GET/v1/oauth/appsList your apps
DELETE/v1/oauth/apps/:idDelete an app

User endpoints (JWT auth)

MethodPathDescription
GET/auth/oauth/authorizeGet app info for consent
POST/auth/oauth/authorizeApprove and issue auth code
POST/auth/oauth/tokenExchange code for API key

Register an app

curl -X POST https://api.brainstormrouter.com/v1/oauth/apps \
  -H "Authorization: Bearer br_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Integration",
    "callback_urls": ["https://myapp.com/callback"],
    "scopes": ["completions", "memory"]
  }'

Returns a client_id (format: br_app_...). No client secret is issued -- PKCE replaces it.

Scopes

ScopeAccess
completionsChat completions
modelsModel listing
memoryMemory read/write
embeddingsEmbeddings API
usageUsage analytics
fullAll access (admin-level)

Default scopes when omitted: completions, models.

Authorization flow

  1. Generate a PKCE verifier and S256 challenge.
  1. Redirect the user to the authorize endpoint:
GET /auth/oauth/authorize?client_id=br_app_...&redirect_uri=https://myapp.com/callback&code_challenge=...&code_challenge_method=S256&scope=completions+memory
  1. User approves. BrainstormRouter redirects back with ?code=....
  1. Exchange the code for a scoped API key:
curl -X POST https://api.brainstormrouter.com/auth/oauth/token \
     -H "Content-Type: application/json" \
     -d '{
       "grant_type": "authorization_code",
       "code": "...",
       "redirect_uri": "https://myapp.com/callback",
       "code_verifier": "original-verifier",
       "client_id": "br_app_..."
     }'
  1. Response:
{
     "key": "br_live_...",
     "scopes": ["completions", "memory"],
     "expires_at": "2026-09-01T00:00:00.000Z"
   }

Auth codes expire after 10 minutes. Issued keys expire after 90 days.

SDK

  • TypeScript SDK: client.oauth.createApp(opts), client.oauth.listApps(),

client.oauth.deleteApp(id)

  • Python SDK: client.oauth.create_app(name, callback_urls), client.oauth.list_apps(),

client.oauth.delete_app(app_id)