Status: [LIVE] Endpoints found: https://openrouter.ai/api/v1 https://openrouter.ai/api/v1` Source: https://github.com/Gasased/affine-openrouter-proxy # affine-openrouter-proxy A tiny, dependency-free proxy that makes a **self-hosted [AFFiNE](https://github.com/toeverything/AFFiNE)** instance's in-app AI work with **[OpenRouter](https://openrouter.ai)** — so you can use any model OpenRouter offers (Claude, GPT, Llama, Qwen, DeepSeek, free models, etc.) inside AFFiNE's Copilot. It runs on [bun](https://bun.sh), has **no external dependencies**, and **stores no secrets** — it forwards your OpenRouter key straight through. ## What & why AFFiNE (self-hosted, tested against v0.26.x) lets you point its **OpenAI provider** at any OpenAI-compatible base URL. The catch: that provider is hardwired to OpenAI's **Responses API**. In `@ai-sdk/openai` v2.0.89 the selection is literally: ```js "responses" in client ? client.responses(id) : client(id) ``` so it always calls `/responses`. OpenRouter only reliably serves **Chat Completions** (`/chat/completions`). Its `/responses` endpoint rejects AFFiNE's payloads — every model returns `Invalid Responses API request`. The two APIs are shaped differently (Responses uses `input` items, `instructions`, `text.format`, and a distinct streaming event schema; Chat Completions uses `messages`, `response_format`, and OpenAI delta chunks), so AFFiNE simply can't talk to OpenRouter directly. This proxy sits in the middle and translates both directions — non-streaming JSON, streaming SSE, and tool / function calls: ``` Responses API Chat Completions API ┌──────────┐ POST /v1/responses ┌────────┐ POST /chat/completions ┌────────────┐ │ AFFiNE │ ─────────────────────▶ │ PROXY │ ─────────────────────────▶ │ OpenRouter │ │ (OpenAI │ ◀───────────────────── │ │ ◀────────