OpenRouter provider

Overview

OpenRouter is a single API key that fronts many upstream models (Anthropic, OpenAI, Google, Meta, Mistral, and others) over one OpenAI-shaped endpoint. mouaif treats it as a first-class provider: same UI flow as any other provider, same SSE streaming, same usage accounting — but the user only has to manage one key to access models from many vendors.

The provider supports two ways to authenticate:

  1. Paste an OpenRouter API key (issued at openrouter.ai). The key is stored in the app SQLite provider record and never returned to the browser after save.

  2. Sign in with OpenRouter (PKCE). The Settings → Providers form now offers a Sign in with OpenRouter button. The browser is sent to https://openrouter.ai/auth?callback_url=...&code_challenge=...&code_challenge_method=S256, the user authorises the app, OpenRouter redirects back to the loopback, the server exchanges the code for a user-controlled OpenRouter API key at https://openrouter.ai/api/v1/auth/keys, and the key is stored in the OS keyring under the openrouter namespace. Subsequent chats use that key as a plain Bearer credential.

    The PKCE flow is the only sign-in option OpenRouter exposes to third-party clients; there is no client_id, no client_secret, no per-app dashboard, and no refresh-token grant. The flow's "OAuth" surface is therefore narrower than Anthropic's or GitHub Copilot's, but it still ships a sign-in button on the provider form so the user can authorise the app in one tap rather than round-tripping through the OpenRouter keys page.

Usage

Add the provider

  1. Settings → Providers → + Add provider.

  2. Pick OpenRouter from the provider dropdown. The default API base URL is https://openrouter.ai/api/v1 (overridable for self-hosted/proxy setups).

  3. Pick an authentication mode:

  1. Save provider. You can now pick OpenRouter when creating a model on a project.

Add a model

  1. In a project, open the project's Models editor.

  2. Set provider: 'openrouter' and id to the OpenRouter model slug as listed on openrouter.ai/models. For example:

{
  "id": "anthropic/claude-3.5-sonnet",
  "provider": "openrouter",
  "label": "Claude 3.5 Sonnet (via OpenRouter)"
}

The full upstream id (including the vendor prefix) is sent verbatim in the chat-completions model field.

  1. The model now appears in the chat head's model picker for any chat in this project.

Chat

No special path. The chat composer posts to /api/chats/:id/messages/stream, which hydrates the project's model with the OpenRouter provider connection, calls https://openrouter.ai/api/v1/chat/completions, and forwards events as SSE. The model picker shows the friendly label; the chat transcript and usage display are identical to every other provider. The key path is transparent: a key obtained via PKCE is used exactly the same way a manually pasted key is.

Behavior