From 029ccd63c79c73e7f0d523cb5c9453a3d43a6555 Mon Sep 17 00:00:00 2001 From: David Lo Dico Date: Wed, 1 Apr 2026 19:20:27 +0200 Subject: [PATCH] feat: add EUrouter as an OpenAI-compatible provider EUrouter is an EU-hosted, GDPR-compliant AI model router. Adds provider config, docs page, sidebar entry, and unit tests. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/my-website/docs/providers/eurouter.md | 101 ++++++++++++++++++ docs/my-website/sidebars.js | 1 + litellm/llms/openai_like/providers.json | 5 + litellm/types/utils.py | 1 + .../llms/openai_like/test_eurouter.py | 76 +++++++++++++ 5 files changed, 184 insertions(+) create mode 100644 docs/my-website/docs/providers/eurouter.md create mode 100644 tests/test_litellm/llms/openai_like/test_eurouter.py diff --git a/docs/my-website/docs/providers/eurouter.md b/docs/my-website/docs/providers/eurouter.md new file mode 100644 index 00000000000..16ad22a04e5 --- /dev/null +++ b/docs/my-website/docs/providers/eurouter.md @@ -0,0 +1,101 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# EUrouter + +[EUrouter](https://eurouter.eu) is an EU-hosted, GDPR-compliant AI model routing service. It's a drop-in replacement for OpenRouter, routing requests to providers like OpenAI, Anthropic, Mistral, Google, and others — with guaranteed EU data residency. + +EUrouter is OpenAI-compatible, so it works with LiteLLM out of the box. + +## Quick Start + +### Environment Variables + +```bash +export EUROUTER_API_KEY="your-eurouter-api-key" +``` + +### Usage + + + + +```python +import litellm + +response = litellm.completion( + model="eurouter/mistral/mistral-large-3", + messages=[{"role": "user", "content": "Hello from the EU!"}], +) +``` + + + + +1. Add to your LiteLLM Proxy config.yaml: + +```yaml +model_list: + - model_name: mistral-large-3 + litellm_params: + model: eurouter/mistral/mistral-large-3 + api_key: os.environ/EUROUTER_API_KEY + - model_name: gpt-4o + litellm_params: + model: eurouter/openai/gpt-4o + api_key: os.environ/EUROUTER_API_KEY + - model_name: claude-sonnet-4-6 + litellm_params: + model: eurouter/anthropic/claude-sonnet-4-6 + api_key: os.environ/EUROUTER_API_KEY +``` + +2. Start the proxy: + +```bash +litellm --config config.yaml +``` + +3. Make a request: + +```bash +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-1234" \ + -d '{ + "model": "mistral-large-3", + "messages": [{"role": "user", "content": "Hello!"}] + }' +``` + + + + +## Supported Models + +EUrouter routes to 100+ models from 15+ providers. Use the `eurouter/` prefix followed by the provider and model name: + +| Model | LiteLLM Model String | +|-------|---------------------| +| Mistral Large 3 | `eurouter/mistral/mistral-large-3` | +| GPT-4o | `eurouter/openai/gpt-4o` | +| GPT-4.1 | `eurouter/openai/gpt-4.1` | +| Claude Sonnet 4.6 | `eurouter/anthropic/claude-sonnet-4-6` | +| Claude Haiku 4.5 | `eurouter/anthropic/claude-haiku-4.5` | +| DeepSeek V3 | `eurouter/deepseek/deepseek-v3` | +| Llama 4 Maverick | `eurouter/meta/llama-4-maverick` | +| Llama 3.3 70B | `eurouter/meta/llama-3.3-70b-instruct` | + +For a full list, visit the [EUrouter Models page](https://eurouter.eu/models) or call: + +```bash +curl https://api.eurouter.ai/api/v1/models +``` + +## Why EUrouter? + +- **EU Data Residency** — Requests are routed only to EU-hosted endpoints +- **GDPR Compliance** — Built for European data protection requirements +- **OpenAI Compatible** — Drop-in replacement, same API format +- **Multi-Provider** — Access OpenAI, Anthropic, Mistral, Google, and more through a single API +- **Transparent Pricing** — Model cost + 5% platform fee, all in EUR diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js index b514ea2234c..bd4a600c5df 100644 --- a/docs/my-website/sidebars.js +++ b/docs/my-website/sidebars.js @@ -907,6 +907,7 @@ const sidebars = { "providers/deepseek", "providers/docker_model_runner", "providers/elevenlabs", + "providers/eurouter", "providers/fal_ai", "providers/featherless_ai", "providers/fireworks_ai", diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index 275c352b39e..880bbe7995f 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -101,5 +101,10 @@ "param_mappings": { "max_completion_tokens": "max_tokens" } + }, + "eurouter": { + "base_url": "https://api.eurouter.ai/api/v1", + "api_key_env": "EUROUTER_API_KEY", + "api_base_env": "EUROUTER_API_BASE" } } diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 82557513a8a..593e0eca76e 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3281,6 +3281,7 @@ class LlmProviders(str, Enum): MANUS = "manus" WANDB = "wandb" OVHCLOUD = "ovhcloud" + EUROUTER = "eurouter" LEMONADE = "lemonade" AMAZON_NOVA = "amazon_nova" A2A_AGENT = "a2a_agent" diff --git a/tests/test_litellm/llms/openai_like/test_eurouter.py b/tests/test_litellm/llms/openai_like/test_eurouter.py new file mode 100644 index 00000000000..9e5afe445ff --- /dev/null +++ b/tests/test_litellm/llms/openai_like/test_eurouter.py @@ -0,0 +1,76 @@ +""" +Tests for EUrouter provider configuration and integration. + +EUrouter is an EU-hosted, GDPR-compliant AI routing service that is +OpenAI-compatible (similar to OpenRouter). +""" + +import os +import sys + +try: + import pytest +except ImportError: + pytest = None + +# Add workspace to path +workspace_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) +sys.path.insert(0, workspace_path) + +import litellm + + +class TestEUrouterProviderConfig: + """Test EUrouter provider configuration""" + + def test_eurouter_in_provider_list(self): + """Test that eurouter is in the provider list""" + from litellm import LlmProviders + + assert hasattr(LlmProviders, "EUROUTER") + assert LlmProviders.EUROUTER.value == "eurouter" + assert "eurouter" in litellm.provider_list + + def test_eurouter_json_config_exists(self): + """Test that eurouter is configured in providers.json""" + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + assert JSONProviderRegistry.exists("eurouter") + + eurouter = JSONProviderRegistry.get("eurouter") + assert eurouter is not None + assert eurouter.base_url == "https://api.eurouter.ai/api/v1" + assert eurouter.api_key_env == "EUROUTER_API_KEY" + + def test_eurouter_provider_resolution(self): + """Test that provider resolution finds eurouter""" + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, api_key, api_base = get_llm_provider( + model="eurouter/mistral/mistral-large-3", + custom_llm_provider=None, + api_base=None, + api_key=None, + ) + + assert provider == "eurouter" + assert api_base == "https://api.eurouter.ai/api/v1" + + def test_eurouter_router_config(self): + """Test that eurouter can be used in Router configuration""" + from litellm import Router + + router = Router( + model_list=[ + { + "model_name": "gpt-4o", + "litellm_params": { + "model": "eurouter/mistral/mistral-large-3", + "api_key": "test-key", + }, + } + ] + ) + + assert len(router.model_list) == 1 + assert router.model_list[0]["model_name"] == "gpt-4o"