Overview
MyRouter provides a unified, OpenAI-compatible API for accessing 200+ AI models from leading providers through a single endpoint.
Request Format
All requests are sent as JSON to the chat completions endpoint. The format is fully compatible with the OpenAI API.
/v1/chat/completionsHeaders
Include these headers with every API request:
AuthorizationstringrequiredBearer sk-myrouter-xxxx — Your API key as a Bearer token. Required.HTTP-RefererstringX-TitlestringResponse Format
Responses follow the standard OpenAI chat completion format.
Structured Outputs
Force the model to return valid JSON matching a schema by using the response_format parameter.
Finish Reasons
The finish_reason field indicates why the model stopped generating:
| Reason | Description |
|---|---|
| stop | Model finished naturally or hit a stop sequence |
| length | Hit max_tokens limit |
| tool_calls | Model invoked one or more tool calls |
| content_filter | Content was filtered by moderation |
| error | An error occurred during generation (streaming only) |
Generation Stats
Query cost and token usage for a specific generation by its ID:
/v1/generation?id={GENERATION_ID}Request Schema (TypeScript)
1interface ChatCompletionRequest {2 model: string; // e.g. "openai/gpt-4o"3 messages: Message[];4 stream?: boolean;5 temperature?: number; // 0-2, default 16 max_tokens?: number;7 top_p?: number; // 0-18 frequency_penalty?: number; // -2 to 29 presence_penalty?: number; // -2 to 210 stop?: string | string[];11 tools?: Tool[];12 tool_choice?: ToolChoice;13 response_format?: ResponseFormat;14 seed?: number;1516 // MyRouter-specific17 models?: string[]; // fallback model list18 route?: "fallback";19 provider?: ProviderPreferences;20}2122interface Message {23 role: "system" | "user" | "assistant" | "tool";24 content: string | ContentPart[];25 name?: string;26 tool_calls?: ToolCall[];27 tool_call_id?: string;28}Structured Outputs
1{2 "model": "openai/gpt-4o",3 "messages": [...],4 "response_format": {5 "type": "json_schema",6 "json_schema": {7 "name": "person",8 "strict": true,9 "schema": {10 "type": "object",11 "properties": {12 "name": { "type": "string" },13 "age": { "type": "integer" }14 },15 "required": ["name", "age"],16 "additionalProperties": false17 }18 }19 }20}Generation Stats
1curl http://148.153.38.18:3010/v1/generation?id=$GENERATION_ID \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Quickstart
Get up and running with MyRouter in under 5 minutes. Make your first API call using the OpenAI SDK.
1. Sign up & create an API key
Register for a free account and generate an API key from the dashboard. No credit card required.
2. Set your API key
Store the key as an environment variable so you never hard-code it into source:
export MYROUTER_API_KEY="sk-myrouter-..."3. Install the SDK
MyRouter is fully OpenAI-compatible — you can use the official OpenAI SDK in any language.
4. Make your first request
Point the SDK at the MyRouter base URL and call chat completions with any supported model.
Next, learn how to secure and rotate keys in Authentication.
First API Call
1from openai import OpenAI23client = OpenAI(4 base_url="http://148.153.38.18:3010/v1",5 api_key="$MYROUTER_API_KEY",6)78response = client.chat.completions.create(9 model="openai/gpt-4o",10 messages=[11 {"role": "user", "content": "Hello, MyRouter!"}12 ],13)1415print(response.choices[0].message.content)Install SDK
1pip install openaiAuthentication
Authenticate your API requests using Bearer tokens. Include your API key in the Authorization header of every request.
Using an API Key
Create API keys from your dashboard. Each key can have an optional credit limit. Include it as a Bearer token in the Authorization header.
We recommend storing your key in an environment variable:
export MYROUTER_API_KEY="sk-myrouter-xxxxxxxxxxxx"Then include it in the request header:
Authorization: Bearer sk-myrouter-xxxxxxxxxxxxSecurity Best Practices
API keys provide full access to your account. Follow these practices to keep them secure:
- !Never expose keys in client-side code or public repositories
- !Use environment variables to store keys
- !Rotate keys periodically and revoke any that may be compromised
- !Set per-key credit limits to control spending
Optional Headers
These optional headers help with analytics and ranking:
HTTP-RefererstringX-TitlestringSDK Configuration
1from openai import OpenAI23client = OpenAI(4 base_url="http://148.153.38.18:3010/v1",5 api_key=os.environ["MYROUTER_API_KEY"],6)78response = client.chat.completions.create(9 model="openai/gpt-4o",10 messages=[11 {"role": "user", "content": "Hello!"}12 ],13)Streaming
Stream responses in real-time using Server-Sent Events (SSE). Set stream: true in your request to enable streaming.
SSE Format
Each SSE event contains a JSON object with partial response data. The stream ends with a special termination signal.
Each SSE event is prefixed with data: followed by a JSON object. The final event is data: [DONE]. The second-to-last chunk contains the usage stats with an empty choices array.
Keepalive Comments
During processing, the server may send SSE comments (lines starting with :) as keepalive signals. These should be ignored per the SSE specification.
Stream Cancellation
Close the connection to cancel a streaming request. The server will stop processing immediately.
Error Handling in Streams
Pre-stream errors
If an error occurs before any tokens are sent, you receive a standard JSON error response with an appropriate HTTP status code (400, 401, 402, 429, etc.).
Mid-stream errors
If an error occurs after tokens have started streaming, the HTTP status remains 200. The error appears as an SSE event with finish_reason: "error" in the choices array.
Streaming Example
1stream = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {"role": "user", "content": "Write a haiku"}5 ],6 stream=True,7)89for chunk in stream:10 content = chunk.choices[0].delta.content11 if content:12 print(content, end="")SSE Stream Format
1: MYROUTER PROCESSING23data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}45data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"The"},"finish_reason":null}]}67data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" capital"},"finish_reason":null}]}89data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":8,"total_tokens":20}}1011data: [DONE]Stream Cancellation
1stream = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[{"role": "user", "content": "Long story"}],4 stream=True,5)67for chunk in stream:8 content = chunk.choices[0].delta.content9 if content and "stop_word" in content:10 stream.close() # Cancel the stream11 break12 print(content, end="")Parameters
Configure model behavior with these request parameters. Not all models support all parameters — unsupported parameters are silently ignored.
Sampling Parameters
temperaturenumberDefault: 1top_pnumberDefault: 1temperature or top_p, not both.top_kintegerDefault: 0frequency_penaltynumberDefault: 0presence_penaltynumberDefault: 0repetition_penaltynumberDefault: 1min_pnumberDefault: 0min_p * top_token_prob are filtered.top_anumberDefault: 0top_a * top_token_prob² are filtered.seedintegerOutput Parameters
max_tokensintegerstopstring | arrayresponse_formatobject{"type": "json_object"} for basic JSON mode, or {"type": "json_schema", ...} for strict schema enforcement.logprobsbooleantop_logprobsintegerlogprobs: true.logit_biasobjectAdvanced Parameters
toolsarraytype ("function") and a function object with name, description, and parameters schema.tool_choicestring | objectDefault: auto"none" (never call), "auto" (model decides), "required" (must call one), or {"type": "function", "function": {"name": "..."}} for a specific function.parallel_tool_callsbooleanDefault: trueSampling Parameters
1response = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {"role": "user", "content": "Tell me a joke"}5 ],6 temperature=0.9,7 top_p=0.95,8 frequency_penalty=0.5,9 presence_penalty=0.3,10 max_tokens=256,11)Tool Calling
1response = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {"role": "user", "content": "What's the weather in Tokyo?"}5 ],6 tools=[7 {8 "type": "function",9 "function": {10 "name": "get_weather",11 "description": "Get current weather",12 "parameters": {13 "type": "object",14 "properties": {15 "location": {"type": "string"}16 },17 "required": ["location"]18 }19 }20 }21 ],22 tool_choice="auto",23)Structured Outputs
1{2 "response_format": {3 "type": "json_schema",4 "json_schema": {5 "name": "analysis",6 "strict": true,7 "schema": {8 "type": "object",9 "properties": {10 "sentiment": {11 "type": "string",12 "enum": ["positive", "negative", "neutral"]13 },14 "confidence": { "type": "number" }15 },16 "required": ["sentiment", "confidence"],17 "additionalProperties": false18 }19 }20 }21}Errors & Debugging
The API uses standard HTTP status codes and returns structured error responses. When an error occurs, the response body contains details about what went wrong.
Error Response Format
Error Codes
| Code | Meaning | Solution |
|---|---|---|
| 400 | Bad Request | Check request body format, parameters, and CORS |
| 401 | Unauthorized | Check your API key is valid and not expired |
| 402 | Payment Required | Insufficient credits — add funds to your account |
| 403 | Forbidden | Input flagged by moderation — modify your content |
| 408 | Request Timeout | Reduce prompt length or increase timeout |
| 429 | Too Many Requests | Rate limited — slow down or upgrade your tier |
| 502 | Bad Gateway | Model is down or returned invalid response — retry |
| 503 | Service Unavailable | No provider meets routing requirements — use fallback models |
Moderation Errors
When input is flagged by content moderation, the error metadata includes the flagged content and the provider that triggered it.
Provider Errors
When the upstream provider returns an error, the raw error details are included in the metadata.
Streaming Errors
During streaming, pre-stream errors return standard HTTP error codes. Mid-stream errors appear as SSE events with finish_reason: "error".
Debug Mode
Enable debug mode to see the transformed request body sent to the upstream provider. Only works with streaming requests.
Debug mode only works with streaming requests. Do not use in production — it exposes internal request transformations.
Error Response Format
1{2 "error": {3 "code": 401,4 "message": "Invalid API key provided.",5 "metadata": {6 "provider_name": "openai"7 }8 }9}Moderation Errors
1{2 "error": {3 "code": 403,4 "message": "Input flagged by content moderation",5 "metadata": {6 "reasons": ["violence", "self-harm"],7 "flagged_input": "...",8 "provider_name": "openai",9 "model_slug": "gpt-4o"10 }11 }12}Debug Mode
1# Debug mode — streaming only2stream = client.chat.completions.create(3 model="openai/gpt-4o",4 messages=[{"role": "user", "content": "Hi"}],5 stream=True,6 extra_body={7 "debug": {"echo_upstream_body": True}8 },9)1011for chunk in stream:12 if hasattr(chunk, "debug"):13 print("Debug:", chunk.debug)14 else:15 content = chunk.choices[0].delta.content16 if content:17 print(content, end="")Retry Example
1import time2from openai import OpenAI, RateLimitError34client = OpenAI(5 base_url="http://148.153.38.18:3010/v1",6 api_key="sk-myrouter-xxxx",7)89for attempt in range(3):10 try:11 response = client.chat.completions.create(12 model="openai/gpt-4o",13 messages=[{"role": "user", "content": "Hi"}],14 )15 break16 except RateLimitError:17 time.sleep(2 ** attempt)Limits
Rate limits protect the API from abuse and ensure fair usage for all users. Limits are applied per API key.
Check Limits
Query your current rate limit status and remaining credits:
/v1/keyRate Limit Tiers
Limits are determined by your account tier:
| Tier | Requests / min | Tokens / min |
|---|---|---|
| Free | 20 | 200,000 |
| Tier 1 | 60 | 1,000,000 |
| Tier 2 | 300 | 10,000,000 |
| Tier 3 | 1,000 | 50,000,000 |
| Enterprise | Custom | Custom |
Response Headers
Rate limit information is included in every API response:
DDoS Protection
Additional Cloudflare-level protection may block requests that exceed reasonable usage patterns. This operates independently of per-key rate limits.
Check Limits
1curl http://148.153.38.18:3010/v1/key \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Response
1{2 "data": {3 "label": "Production Key",4 "limit": 100.0,5 "limit_remaining": 74.5,6 "limit_reset": "monthly",7 "usage": 25.5,8 "usage_daily": 3.2,9 "usage_weekly": 12.8,10 "usage_monthly": 25.5,11 "is_free_tier": false12 }13}Response Headers
1X-RateLimit-Limit-Requests: 602X-RateLimit-Limit-Tokens: 10000003X-RateLimit-Remaining-Requests: 594X-RateLimit-Remaining-Tokens: 9995005X-RateLimit-Reset-Requests: 1s6X-RateLimit-Reset-Tokens: 30msTool Calling
Let the model invoke functions in your application. Define tool schemas, send them with your request, and the model decides when and how to call them.
How It Works
Tool calling follows a simple back-and-forth loop:
- You describe available tools as JSON schemas in the tools parameter.
- The model responds with either text or tool_calls containing function name and arguments.
- Your code executes each tool call and appends a tool message with the result.
- You call the API again — the model uses the results to produce the final answer or more tool calls.
Parameters
toolsarrayrequiredtool_choicestring | objectDefault: auto"none", "auto", "required" or a specific function object to force the model's choice.parallel_tool_callsbooleanDefault: trueMulti-Turn Loop
Run the request-execute-respond loop until the model returns a plain text message with no more tool calls.
Note: Not all models support tool calling. Check the model capabilities or use provider.require_parameters to auto-filter.
Defining Tools
1tools = [2 {3 "type": "function",4 "function": {5 "name": "get_weather",6 "description": "Get current weather for a city",7 "parameters": {8 "type": "object",9 "properties": {10 "city": {"type": "string"},11 "unit": {12 "type": "string",13 "enum": ["celsius", "fahrenheit"]14 }15 },16 "required": ["city"]17 }18 }19 }20]2122response = client.chat.completions.create(23 model="openai/gpt-4o",24 messages=[25 {"role": "user", "content": "Weather in Tokyo?"}26 ],27 tools=tools,28 tool_choice="auto",29)Multi-Turn Loop
1messages = [{"role": "user", "content": "Weather in Tokyo?"}]23while True:4 response = client.chat.completions.create(5 model="openai/gpt-4o",6 messages=messages,7 tools=tools,8 )9 msg = response.choices[0].message10 messages.append(msg)1112 if not msg.tool_calls:13 print(msg.content)14 break1516 for call in msg.tool_calls:17 result = run_tool(call.function.name, call.function.arguments)18 messages.append({19 "role": "tool",20 "tool_call_id": call.id,21 "content": result,22 })Response with Tool Calls
1{2 "choices": [{3 "message": {4 "role": "assistant",5 "content": null,6 "tool_calls": [{7 "id": "call_abc123",8 "type": "function",9 "function": {10 "name": "get_weather",11 "arguments": "{\"city\":\"Tokyo\"}"12 }13 }]14 },15 "finish_reason": "tool_calls"16 }]17}Structured Outputs
Force the model to produce output in a specific JSON shape. Two modes are supported: loose JSON object mode and strict JSON schema mode.
JSON Object Mode
Simpler mode — the model is asked to produce valid JSON, but the structure is not enforced. Include "JSON" in the system prompt for best results.
JSON Schema Mode
Strict mode — the model is constrained to output JSON matching your exact schema. Available on supported models with 100% accuracy.
namestringrequiredstrictbooleanDefault: falseschemaobjectrequiredBest Practices
- Set strict: true and additionalProperties: false for guaranteed conformance.
- All fields should be marked required — use enum or nullable types for optional data.
- Avoid deeply nested schemas (>5 levels) as they slow down generation.
- Keep field names descriptive — the model uses them as hints.
Supported on GPT-4o, Claude, Gemini, DeepSeek, and most Qwen models. The API will return an error if the model doesn't support the chosen mode.
JSON Object Mode
1response = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {"role": "system", "content": "Output JSON only."},5 {"role": "user", "content": "List 3 capitals."}6 ],7 response_format={"type": "json_object"},8)910import json11data = json.loads(response.choices[0].message.content)JSON Schema Mode
1response = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {"role": "user", "content": "Extract: Alice is 30 years old."}5 ],6 response_format={7 "type": "json_schema",8 "json_schema": {9 "name": "person",10 "strict": True,11 "schema": {12 "type": "object",13 "properties": {14 "name": {"type": "string"},15 "age": {"type": "integer"}16 },17 "required": ["name", "age"],18 "additionalProperties": False19 }20 }21 }22)Complex Schema
1{2 "type": "json_schema",3 "json_schema": {4 "name": "analysis",5 "strict": true,6 "schema": {7 "type": "object",8 "properties": {9 "sentiment": {10 "type": "string",11 "enum": ["positive", "negative", "neutral"]12 },13 "score": { "type": "number" },14 "keywords": {15 "type": "array",16 "items": { "type": "string" }17 }18 },19 "required": ["sentiment", "score", "keywords"],20 "additionalProperties": false21 }22 }23}Vision
Send images alongside text prompts to vision-capable models. Multimodal content uses content parts — an array of text and image_url objects.
Content Parts
Instead of a plain string, pass content as an array of typed parts. Each part is either text or image_url.
typestringrequired"text" for plain text, "image_url" for images.image_url.urlstringrequiredimage_url.detailstringDefault: auto"low", "high", "auto" — resolution hint. "high" uses more tokens for better analysis.Supported Models
Popular vision-capable models include:
openai/gpt-4o,openai/gpt-4o-minianthropic/claude-sonnet-4,anthropic/claude-opus-4google/gemini-2.5-pro,google/gemini-2.5-flashqwen/qwen-vl-max,meta/llama-3.2-vision
Limits & Notes
- Max 20 images per request.
- Max 20 MB per image — larger images are rejected.
- Supported formats: PNG, JPEG, WebP, non-animated GIF.
URL Image
1response = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {5 "role": "user",6 "content": [7 {"type": "text", "text": "What is in this image?"},8 {9 "type": "image_url",10 "image_url": {11 "url": "https://example.com/cat.jpg"12 }13 }14 ]15 }16 ],17)Base64 Image
1import base6423with open("cat.jpg", "rb") as f:4 b64 = base64.b64encode(f.read()).decode()56response = client.chat.completions.create(7 model="openai/gpt-4o",8 messages=[{9 "role": "user",10 "content": [11 {"type": "text", "text": "Describe this."},12 {13 "type": "image_url",14 "image_url": {15 "url": f"data:image/jpeg;base64,{b64}"16 }17 }18 ]19 }]20)Multiple Images
1{2 "messages": [{3 "role": "user",4 "content": [5 { "type": "text", "text": "Compare these two images." },6 { "type": "image_url",7 "image_url": { "url": "https://example.com/a.png" }},8 { "type": "image_url",9 "image_url": { "url": "https://example.com/b.png" }}10 ]11 }]12}Reasoning Tokens
Some models generate a hidden chain-of-thought before their final answer. Control reasoning depth and access the traces via the reasoning parameter.
Supported Models
Reasoning is currently supported by:
openai/o1,openai/o3-mini— with effort levelsdeepseek/deepseek-r1— open-source reasoning modelanthropic/claude-opus-4— via extended thinkinggoogle/gemini-2.5-pro— with reasoning tokens
Parameters
reasoning.effortstring"low", "medium", "high" — reasoning budget as a rough dial. Maps to provider-specific settings.reasoning.max_tokensintegerreasoning.excludebooleanDefault: falseBilling
Reasoning tokens are billed at the model's output token rate. They appear as reasoning_tokens in the usage object.
Reasoning models can be slow and expensive. Use effort: "low" or max_tokens: 1000 for cost-sensitive workloads.
Effort Levels
1response = client.chat.completions.create(2 model="openai/o1",3 messages=[4 {"role": "user", "content": "Prove that sqrt(2) is irrational."}5 ],6 extra_body={7 "reasoning": {8 "effort": "high",9 "exclude": False10 }11 }12)1314print(response.choices[0].message.reasoning)15print(response.choices[0].message.content)Token Budget
1{2 "model": "anthropic/claude-opus-4",3 "messages": [...],4 "reasoning": {5 "max_tokens": 4096,6 "exclude": false7 }8}Response with Reasoning
1{2 "choices": [{3 "message": {4 "role": "assistant",5 "reasoning": "First, let me consider...",6 "content": "The answer is..."7 }8 }],9 "usage": {10 "prompt_tokens": 25,11 "completion_tokens": 142,12 "reasoning_tokens": 1024,13 "total_tokens": 119114 }15}Prompt Caching
Reuse expensive prompt prefixes across requests to save tokens and latency. MyRouter normalizes caching across providers.
How It Works
When consecutive requests share a long common prefix (system prompt, few-shot examples, documents), the provider stores the KV-cache and skips re-processing on subsequent calls.
Anthropic — Explicit
Anthropic requires explicit cache_control breakpoints. Place up to 4 cache markers at the end of stable segments.
OpenAI & DeepSeek — Automatic
OpenAI and DeepSeek cache automatically when the prefix exceeds 1024 tokens. No code changes needed — just reuse the same prefix.
Google Gemini — Implicit
Gemini 2.5 models cache implicitly for prompts over 2048 tokens. Explicit cached content API is also available for larger contexts.
Pricing Impact
| Provider | Cache Write | Cache Read |
|---|---|---|
| Anthropic | 1.25x | 0.1x |
| OpenAI | 1x | 0.5x |
| DeepSeek | 1x | 0.1x |
| Google Gemini | 1x | 0.25x |
Multipliers applied to base input token price. Cached reads are dramatically cheaper than uncached.
Anthropic — Explicit
1{2 "model": "anthropic/claude-sonnet-4",3 "messages": [4 {5 "role": "system",6 "content": [{7 "type": "text",8 "text": "Very long system prompt...",9 "cache_control": { "type": "ephemeral" }10 }]11 },12 { "role": "user", "content": "Question 1" }13 ]14}Usage Reporting
1{2 "usage": {3 "prompt_tokens": 1523,4 "completion_tokens": 87,5 "total_tokens": 1610,6 "prompt_tokens_details": {7 "cached_tokens": 14008 },9 "cache_creation_input_tokens": 0,10 "cache_read_input_tokens": 140011 }12}OpenAI & DeepSeek — Automatic
1# OpenAI and DeepSeek cache automatically.2# Just reuse the same prompt prefix across requests.3for question in questions:4 response = client.chat.completions.create(5 model="openai/gpt-4o",6 messages=[7 {"role": "system", "content": LONG_SYSTEM_PROMPT},8 {"role": "user", "content": question}9 ],10 )Web Search
Ground your model's responses in live web results. Two ways to enable: a model suffix or an explicit plugin.
Model Suffix (:online)
Append :online to any model ID. MyRouter will run a web search before calling the model and inject the results into the prompt. No other code changes needed.
Web Plugin
For more control, pass a plugins array with a web plugin. Configure result count and search prompt.
idstringrequired"web" — always "web" for the web search plugin.max_resultsintegerDefault: 5search_promptstringCitations
Responses include an annotations array with url_citation objects — one per source used by the model.
Pricing
Web search is billed separately from token usage — $0.004 per result by default.
Model Suffix (:online)
1response = client.chat.completions.create(2 model="openai/gpt-4o:online",3 messages=[4 {"role": "user", "content": "Latest news on AI?"}5 ],6)78for citation in response.choices[0].message.annotations:9 print(citation["url_citation"]["url"])Web Plugin
1{2 "model": "openai/gpt-4o",3 "messages": [...],4 "plugins": [{5 "id": "web",6 "max_results": 5,7 "search_prompt": "Search for recent news about:"8 }]9}Citations
1{2 "choices": [{3 "message": {4 "role": "assistant",5 "content": "...",6 "annotations": [7 {8 "type": "url_citation",9 "url_citation": {10 "url": "https://example.com/article",11 "title": "Article title",12 "content": "Snippet excerpt..."13 }14 }15 ]16 }17 }]18}Embeddings
Get vector representations of text for similarity search, clustering, classification, and RAG (Retrieval-Augmented Generation).
What are Embeddings?
Embeddings are numerical vector representations of text that capture semantic meaning. Similar texts produce vectors that are close together in the embedding space.
Common Use Cases
/v1/embeddingsAvailable Models
| Model | Dimensions | Max Tokens |
|---|---|---|
| openai/text-embedding-3-small | 1536 | 8191 |
| openai/text-embedding-3-large | 3072 | 8191 |
| openai/text-embedding-ada-002 | 1536 | 8191 |
| cohere/embed-english-v3.0 | 1024 | 512 |
| cohere/embed-multilingual-v3.0 | 1024 | 512 |
Best Practices
Tips for working effectively with embeddings:
- •Choose the right model size — smaller models are faster and cheaper for simple tasks
- •Batch requests to reduce overhead and improve throughput
- •Cache embeddings to avoid recomputing for the same text
- •Use cosine similarity for comparing embedding vectors
- •Consider your model's context length when chunking long documents
Basic Request
1response = client.embeddings.create(2 model="openai/text-embedding-3-small",3 input="The quick brown fox jumps over the lazy dog",4)56embedding = response.data[0].embedding7print(f"Dimensions: {len(embedding)}")Batch Processing
1response = client.embeddings.create(2 model="openai/text-embedding-3-small",3 input=[4 "First document text",5 "Second document text",6 "Third document text",7 ],8)910for item in response.data:11 print(f"[{item.index}] dims={len(item.embedding)}")Semantic Search
1import numpy as np23def cosine_similarity(a, b):4 return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))56# Embed the query7query_resp = client.embeddings.create(8 model="openai/text-embedding-3-small",9 input="How to deploy a web app?",10)11query_vec = query_resp.data[0].embedding1213# Compare against stored document embeddings14for doc in documents:15 score = cosine_similarity(query_vec, doc["embedding"])16 print(f"{score:.4f} — {doc['title']}")POST /v1/chat/completions
Create a chat completion using any supported model. This is the primary endpoint for generating AI responses.
/v1/chat/completionsRequest Body
modelstringrequiredopenai/gpt-4o, anthropic/claude-sonnet-4, deepseek/deepseek-chatmessagesarrayrequiredrole ("system", "user", "assistant", "tool") and content (string or content parts array).streambooleanDefault: falsetemperaturenumberDefault: 1max_tokensintegertop_pnumberDefault: 1stopstring | arraytoolsarraytool_choicestring | objectDefault: auto"none", "auto", "required", or specific function.response_formatobject{"type": "json_object"} or JSON schema mode.frequency_penaltynumberDefault: 0presence_penaltynumberDefault: 0seedintegerProvider Preferences
Control which providers handle your request with the provider parameter:
provider.orderstring[]["openai", "azure", "anthropic"]provider.allow_fallbacksbooleanDefault: trueprovider.require_parametersbooleanDefault: falseprovider.data_collectionstring"deny" or "allow"provider.quantizationsstring[]int4, int8, fp8, fp16, bf16, etc.Response
A successful response returns a chat completion object:
idstringobjectstring"chat.completion" (or "chat.completion.chunk" for streaming).modelstringchoicesarrayindex, message (role + content), and finish_reason.usageobjectprompt_tokens, completion_tokens, total_tokens.Request Example
1response = client.chat.completions.create(2 model="openai/gpt-4o",3 messages=[4 {5 "role": "system",6 "content": "You are a helpful assistant."7 },8 {9 "role": "user",10 "content": "What is the capital of France?"11 }12 ],13 temperature=0.7,14 max_tokens=256,15 extra_body={16 "provider": {17 "order": ["openai", "azure"],18 "allow_fallbacks": True,19 }20 },21)Response
1{2 "id": "chatcmpl-abc123",3 "object": "chat.completion",4 "created": 1700000000,5 "model": "openai/gpt-4o",6 "choices": [7 {8 "index": 0,9 "message": {10 "role": "assistant",11 "content": "The capital of France is Paris."12 },13 "finish_reason": "stop"14 }15 ],16 "usage": {17 "prompt_tokens": 25,18 "completion_tokens": 8,19 "total_tokens": 3320 }21}POST /v1/completions
Legacy text completion endpoint for instruct models. Compatible with the old OpenAI /v1/completions shape.
/v1/completionsLegacy: For new projects, use the chat completions endpoint instead: /v1/chat/completions.
Request Body
modelstringrequiredpromptstring | string[]requiredmax_tokensintegertemperaturenumberDefault: 1top_pnumberDefault: 1stopstring | string[]streambooleanDefault: falsesuffixstringechobooleanDefault: falseRequest Example
1response = client.completions.create(2 model="openai/gpt-3.5-turbo-instruct",3 prompt="Once upon a time,",4 max_tokens=128,5 temperature=0.8,6)78print(response.choices[0].text)Response
1{2 "id": "cmpl-abc123",3 "object": "text_completion",4 "created": 1700000000,5 "model": "openai/gpt-3.5-turbo-instruct",6 "choices": [{7 "text": " there was a brave knight...",8 "index": 0,9 "finish_reason": "length"10 }],11 "usage": {12 "prompt_tokens": 5,13 "completion_tokens": 128,14 "total_tokens": 13315 }16}GET /v1/models
Returns a list of all available models and their properties, including pricing, context length, and capabilities.
/v1/modelsQuery Parameters
categorystringprogramming, roleplay, marketing, science, translation, etc.supported_parametersstringtools,response_formatoutput_modalitiesstringDefault: texttext, image, audio, embeddings, allModel Object
Each model object in the response contains:
idstringopenai/gpt-4onamestringdescriptionstringcontext_lengthintegerpricingobjectprompt, completion, request, image.architectureobjecttokenizer, instruct_type, input_modalities, output_modalities.top_providerobjectcontext_length, max_completion_tokens, is_moderated.supported_parametersstring[]knowledge_cutoffstringRequest Example
1curl http://148.153.38.18:3010/v1/models \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Response
1{2 "object": "list",3 "data": [4 {5 "id": "openai/gpt-4o",6 "name": "GPT-4o",7 "created": 1700000000,8 "description": "Most capable GPT-4 model...",9 "context_length": 128000,10 "pricing": {11 "prompt": "0.0000025",12 "completion": "0.00001",13 "request": "0",14 "image": "0.003613"15 },16 "architecture": {17 "tokenizer": "GPT",18 "instruct_type": "chatml",19 "input_modalities": ["text", "image"],20 "output_modalities": ["text"]21 },22 "top_provider": {23 "context_length": 128000,24 "max_completion_tokens": 16384,25 "is_moderated": true26 },27 "supported_parameters": [28 "temperature", "top_p", "max_tokens",29 "tools", "response_format", "seed"30 ]31 },32 {33 "id": "anthropic/claude-sonnet-4",34 "name": "Claude Sonnet 4",35 "created": 1700000000,36 "context_length": 200000,37 "pricing": {38 "prompt": "0.000003",39 "completion": "0.000015"40 },41 "architecture": {42 "tokenizer": "Claude",43 "input_modalities": ["text", "image"],44 "output_modalities": ["text"]45 }46 }47 ]48}GET /v1/models/:author/:slug/endpoints
List all available provider endpoints for a specific model, including pricing, latency, and throughput information.
/v1/models/:author/:slug/endpointsPath Parameters
authorstringrequiredopenai, anthropicslugstringrequiredgpt-4o, claude-sonnet-4Response
Returns an array of endpoint objects for the specified model:
provider_namestringOpenAI, Azurecontext_lengthintegermax_completion_tokensintegerpricingobjectprompt, completion.quantizationstringfp16, fp8, int8, int4, etc.latency_last_30mobjectp50, p75, p90, p99.throughput_last_30mobjectp50, p75, p90, p99.uptime_last_30mnumberstatusinteger0 = operational.Request Example
1curl http://148.153.38.18:3010/v1/models/openai/gpt-4o/endpoints \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Response
1{2 "data": {3 "id": "openai/gpt-4o",4 "name": "GPT-4o",5 "endpoints": [6 {7 "provider_name": "OpenAI",8 "model_id": "openai/gpt-4o",9 "context_length": 128000,10 "max_completion_tokens": 16384,11 "pricing": {12 "prompt": "0.0000025",13 "completion": "0.00001"14 },15 "quantization": "fp16",16 "supported_parameters": [17 "temperature", "top_p", "tools"18 ],19 "latency_last_30m": {20 "p50": 0.45,21 "p75": 0.62,22 "p90": 0.91,23 "p99": 1.8524 },25 "throughput_last_30m": {26 "p50": 85,27 "p75": 72,28 "p90": 55,29 "p99": 3230 },31 "uptime_last_30m": 99.8,32 "status": 033 },34 {35 "provider_name": "Azure",36 "model_id": "openai/gpt-4o",37 "context_length": 128000,38 "pricing": {39 "prompt": "0.0000027",40 "completion": "0.000011"41 },42 "quantization": "fp16"43 }44 ]45 }46}GET /v1/providers
Returns a list of all available model providers with their metadata.
/v1/providersResponse
Returns an array of provider objects:
namestringOpenAI, Anthropicslugstringopenai, anthropicheadquartersstringUS, CNdatacentersstring[]["US", "EU", "APAC"]privacy_policy_urlstringterms_of_service_urlstringstatus_page_urlstringRequest Example
1curl http://148.153.38.18:3010/v1/providers \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Response
1{2 "data": [3 {4 "name": "OpenAI",5 "slug": "openai",6 "headquarters": "US",7 "datacenters": ["US", "IE"],8 "privacy_policy_url": "https://openai.com/privacy",9 "terms_of_service_url": "https://openai.com/terms",10 "status_page_url": "https://status.openai.com"11 },12 {13 "name": "Anthropic",14 "slug": "anthropic",15 "headquarters": "US",16 "datacenters": ["US"],17 "privacy_policy_url": "https://anthropic.com/privacy"18 },19 {20 "name": "Google",21 "slug": "google",22 "headquarters": "US",23 "datacenters": ["US", "EU", "APAC"]24 },25 {26 "name": "DeepSeek",27 "slug": "deepseek",28 "headquarters": "CN",29 "datacenters": ["CN", "US"]30 }31 ]32}GET /v1/generation
Look up exact token counts, cost, latency, and cache stats for any past request using its id.
/v1/generation?id={GENERATION_ID}Stats are available ~200ms after the request completes. Useful for analytics, cost attribution, and debugging.
Query Parameters
idstringrequiredResponse
modelstringproviderstringtokens_prompt / tokens_completionintegernative_tokens_*integertotal_costnumberlatency_msintegercache_discountnumberfinish_reasonstringRequest Example
1curl "http://148.153.38.18:3010/v1/generation?id=gen-abc123" \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Response
1{2 "data": {3 "id": "gen-abc123",4 "model": "openai/gpt-4o",5 "provider": "openai",6 "created_at": "2026-04-07T10:00:00Z",7 "tokens_prompt": 1523,8 "tokens_completion": 87,9 "native_tokens_prompt": 1512,10 "native_tokens_completion": 89,11 "cache_discount": 0.72,12 "total_cost": 0.00234,13 "latency_ms": 1840,14 "finish_reason": "stop",15 "streamed": true16 }17}GET /v1/credits
Query your current credit balance, usage, and rate limits. Safe to call frequently — cached briefly upstream.
/v1/creditsResponse
total_creditsnumbertotal_usagenumberrate_limitobjectis_free_tierbooleanSurface this in your dashboard so users know when they're running low.
Request Example
1curl http://148.153.38.18:3010/v1/credits \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Response
1{2 "data": {3 "total_credits": 100.00,4 "total_usage": 23.45,5 "rate_limit": {6 "requests": 600,7 "interval": "1m"8 },9 "is_free_tier": false10 }11}POST /v1/images/generations
Generate images from a text prompt. OpenAI DALL-E, Black Forest Labs FLUX, Stable Diffusion, and Google Imagen are supported.
/v1/images/generationsRequest Body
modelstringrequiredopenai/dall-e-3, black-forest-labs/flux-1.1-pro, stabilityai/sdxlpromptstringrequiredsizestringDefault: 1024x1024256x256, 512x512, 1024x1024, 1024x1792, 1792x1024nintegerDefault: 1qualitystringDefault: standard"standard", "hd" — higher quality takes longer and costs more (DALL-E 3 only).stylestringDefault: vivid"vivid", "natural" — vivid is hyper-real and dramatic; natural is more photographic (DALL-E 3 only).response_formatstringDefault: url"url", "b64_json"seedintegerSupported Models
openai/dall-e-3,openai/dall-e-2black-forest-labs/flux-1.1-pro,black-forest-labs/flux-schnellstabilityai/stable-diffusion-3.5-largegoogle/imagen-3
Request Example
1response = client.images.generate(2 model="black-forest-labs/flux-1.1-pro",3 prompt="A cyberpunk cat in neon lights",4 size="1024x1024",5 n=1,6)78print(response.data[0].url)Response
1{2 "created": 1700000000,3 "data": [4 {5 "url": "https://cdn.myrouter.ai/img/abc.png",6 "revised_prompt": "A cyberpunk cat under neon lights..."7 }8 ]9}POST /v1/audio/speech
Convert text to natural-sounding speech. Returns an audio stream you can pipe to a file or play directly.
/v1/audio/speechRequest Body
modelstringrequiredopenai/tts-1, openai/tts-1-hd, fishaudio/fish-speech-1.5inputstringrequiredvoicestringrequiredalloy, echo, fable, onyx, nova, shimmerresponse_formatstringDefault: mp3mp3, opus, aac, flac, wav, pcmspeednumberDefault: 1.0Response
The response body is raw audio bytes in the requested format. Use the SDK's stream_to_file helper or read chunks directly.
Request Example
1response = client.audio.speech.create(2 model="openai/tts-1-hd",3 voice="alloy",4 input="The quick brown fox jumps over the lazy dog.",5 response_format="mp3",6 speed=1.0,7)89response.stream_to_file("output.mp3")POST /v1/audio/transcriptions
Transcribe audio to text. Supports Whisper and other speech-to-text models via multipart/form-data upload.
/v1/audio/transcriptionsContent-Type: multipart/form-data
Request Body
filefilerequiredmodelstringrequiredopenai/whisper-1, deepgram/nova-2, fishaudio/sense-voice-smalllanguagestringpromptstringresponse_formatstringDefault: jsonjson, text, srt, verbose_json, vtttemperaturenumberDefault: 0timestamp_granularitiesarray["word"] or ["segment"] — request word-level or segment-level timestamps (verbose_json only).File size limit: 25 MB. For longer audio, split before uploading.
Request Example
1with open("audio.mp3", "rb") as f:2 response = client.audio.transcriptions.create(3 model="openai/whisper-1",4 file=f,5 language="en",6 response_format="json",7 temperature=0,8 )910print(response.text)Response (verbose_json)
1{2 "task": "transcribe",3 "language": "english",4 "duration": 12.5,5 "text": "The quick brown fox jumps over the lazy dog.",6 "segments": [7 {8 "id": 0,9 "start": 0.0,10 "end": 3.2,11 "text": "The quick brown fox",12 "avg_logprob": -0.2313 }14 ]15}POST /v1/embeddings
Generate vector embeddings for text input. Returns embedding vectors that can be used for similarity search, clustering, and other tasks.
/v1/embeddingsRequest Body
modelstringrequiredopenai/text-embedding-3-smallinputstring | arrayrequiredencoding_formatstringDefault: floatfloat or base64.dimensionsintegertext-embedding-3 models.Response
objectstring"list".dataarrayindex and embedding (float array).modelstringusageobjectprompt_tokens, total_tokens.Request Example
1response = client.embeddings.create(2 model="openai/text-embedding-3-small",3 input="The quick brown fox jumps over the lazy dog",4 encoding_format="float",5)67print(response.data[0].embedding[:5])8# [0.0023, -0.0091, 0.0152, ...]Response
1{2 "object": "list",3 "data": [4 {5 "object": "embedding",6 "index": 0,7 "embedding": [0.0023, -0.0091, 0.0152, ...]8 }9 ],10 "model": "openai/text-embedding-3-small",11 "usage": {12 "prompt_tokens": 9,13 "total_tokens": 914 }15}POST /v1/rerank
Re-rank a list of documents by relevance to a query. Used in RAG pipelines to improve retrieval quality before feeding context to an LLM.
/v1/rerankUse Cases
- Improve RAG quality by re-scoring top-K retrieved documents with a cross-encoder.
- Build semantic search with a cheap first-stage vector retriever + rerank for precision.
- De-duplicate or filter noisy retrieval results.
Request Body
modelstringrequiredcohere/rerank-v3.5, baai/bge-reranker-v2-m3querystringrequireddocumentsstring[] | object[]requiredtop_nintegerreturn_documentsbooleanDefault: falsemax_chunks_per_docintegerDefault: 10Response
resultsarrayresults[].indexintegerresults[].relevance_scorenumberRequest Example
1import requests23response = requests.post(4 "http://148.153.38.18:3010/v1/rerank",5 headers={"Authorization": "Bearer $MYROUTER_API_KEY"},6 json={7 "model": "cohere/rerank-v3.5",8 "query": "What is the capital of France?",9 "documents": [10 "Paris is the capital of France.",11 "Berlin is in Germany.",12 "Tokyo is the capital of Japan.",13 ],14 "top_n": 2,15 "return_documents": True,16 },17)18print(response.json())Response
1{2 "id": "rerank-abc123",3 "results": [4 {5 "index": 0,6 "relevance_score": 0.98,7 "document": { "text": "Paris is the capital of France." }8 },9 {10 "index": 2,11 "relevance_score": 0.12,12 "document": { "text": "Tokyo is the capital of Japan." }13 }14 ],15 "meta": {16 "billed_units": { "search_units": 1 }17 }18}Frameworks & SDKs
MyRouter is OpenAI-compatible, so it works out of the box with any library that talks to the OpenAI API. Below are setup snippets for the most popular frameworks.
OpenAI SDK
Swap the base URL and API key — that's it. Everything else (streaming, tools, structured outputs) just works.
- Drop-in replacement — no code changes beyond base_url and api_key.
- Tool calling, streaming, vision, and structured outputs all work as-is.
- Available in Python, Node.js, Go, .NET, Java and more.
LangChain
Use the ChatOpenAI class from langchain-openai and point it at MyRouter's base URL.
- Use ChatOpenAI with bind_tools() to expose Python @tool functions to the model.
- Compatible with LangGraph agents, RunnableWithMessageHistory, and the LCEL pipeline.
- Both langchain-openai (Python) and @langchain/openai (JS) support tool calls.
Vercel AI SDK
Use createOpenAI from @ai-sdk/openai to construct a provider that hits MyRouter.
- Define tools with Zod schemas — fully type-safe end-to-end.
- Use maxSteps to enable multi-turn tool execution loops automatically.
- Works with streamText, generateText, and the React useChat hook.
LlamaIndex
LlamaIndex exposes OpenAILike for any OpenAI-compatible endpoint — drop in the base URL and key.
- Wrap any Python function with FunctionTool.from_defaults() to expose it.
- Use ReActAgent or FunctionCallingAgent for autonomous tool-using agents.
- Set is_function_calling_model=True so LlamaIndex routes via the tools API.
Tool Calling Tip: Pick a model that supports function calling — GPT-4o, Claude 3.5+, Gemini 1.5+, DeepSeek-V3, and most Qwen 2.5+ models work. Use provider.require_parameters: true to auto-skip providers that don't.
Other Frameworks
MyRouter is compatible with essentially every framework that supports a custom OpenAI base URL:
- Semantic Kernel · Mastra · PydanticAI · Haystack
- Continue · Cursor · Cline · Aider
- Any tool that accepts an OPENAI_BASE_URL or OPENAI_API_BASE environment variable
OpenAI SDK · Setup
1from openai import OpenAI23client = OpenAI(4 base_url="http://148.153.38.18:3010/v1",5 api_key="$MYROUTER_API_KEY",6)OpenAI SDK · Tool Calling
1import json2from openai import OpenAI34client = OpenAI(5 base_url="http://148.153.38.18:3010/v1",6 api_key="$MYROUTER_API_KEY",7)89tools = [{10 "type": "function",11 "function": {12 "name": "get_weather",13 "description": "Get current weather for a city",14 "parameters": {15 "type": "object",16 "properties": {17 "city": {"type": "string", "description": "City name"},18 "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},19 },20 "required": ["city"],21 },22 },23}]2425def get_weather(city: str, unit: str = "celsius"):26 return {"city": city, "temp": 22, "unit": unit, "condition": "Sunny"}2728messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]2930resp = client.chat.completions.create(31 model="openai/gpt-4o",32 messages=messages,33 tools=tools,34 tool_choice="auto",35)3637msg = resp.choices[0].message38messages.append(msg)3940for call in msg.tool_calls or []:41 args = json.loads(call.function.arguments)42 result = get_weather(**args)43 messages.append({44 "role": "tool",45 "tool_call_id": call.id,46 "content": json.dumps(result),47 })4849final = client.chat.completions.create(50 model="openai/gpt-4o",51 messages=messages,52 tools=tools,53)54print(final.choices[0].message.content)LangChain · Setup
1from langchain_openai import ChatOpenAI23llm = ChatOpenAI(4 model="openai/gpt-4o",5 base_url="http://148.153.38.18:3010/v1",6 api_key="$MYROUTER_API_KEY",7)LangChain · Tool Calling
1from langchain_core.tools import tool2from langchain_openai import ChatOpenAI34@tool5def get_weather(city: str, unit: str = "celsius") -> dict:6 """Get current weather for a city."""7 return {"city": city, "temp": 22, "unit": unit, "condition": "Sunny"}89llm = ChatOpenAI(10 model="openai/gpt-4o",11 base_url="http://148.153.38.18:3010/v1",12 api_key="$MYROUTER_API_KEY",13)1415llm_with_tools = llm.bind_tools([get_weather])16messages = [("user", "What's the weather in Tokyo?")]1718ai_msg = llm_with_tools.invoke(messages)19messages.append(ai_msg)2021for call in ai_msg.tool_calls:22 tool_msg = get_weather.invoke(call)23 messages.append(tool_msg)2425final = llm_with_tools.invoke(messages)26print(final.content)Vercel AI SDK · Setup
1import { createOpenAI } from "@ai-sdk/openai";2import { generateText } from "ai";34const myrouter = createOpenAI({5 baseURL: "http://148.153.38.18:3010/v1",6 apiKey: process.env.MYROUTER_API_KEY,7});89const { text } = await generateText({10 model: myrouter("openai/gpt-4o"),11 prompt: "Hello",12});Vercel AI SDK · Tool Calling
1import { createOpenAI } from "@ai-sdk/openai";2import { generateText, tool } from "ai";3import { z } from "zod";45const myrouter = createOpenAI({6 baseURL: "http://148.153.38.18:3010/v1",7 apiKey: process.env.MYROUTER_API_KEY,8});910const { text, toolResults } = await generateText({11 model: myrouter("openai/gpt-4o"),12 maxSteps: 5, // multi-turn tool loop13 prompt: "What's the weather in Tokyo?",14 tools: {15 get_weather: tool({16 description: "Get current weather for a city",17 parameters: z.object({18 city: z.string().describe("City name"),19 unit: z.enum(["celsius", "fahrenheit"]).optional(),20 }),21 execute: async ({ city, unit = "celsius" }) => ({22 city,23 temp: 22,24 unit,25 condition: "Sunny",26 }),27 }),28 },29});3031console.log(text);LlamaIndex · Setup
1from llama_index.llms.openai_like import OpenAILike23llm = OpenAILike(4 model="openai/gpt-4o",5 api_base="http://148.153.38.18:3010/v1",6 api_key="$MYROUTER_API_KEY",7 is_chat_model=True,8 is_function_calling_model=True,9)LlamaIndex · Tool Calling
1from llama_index.core.tools import FunctionTool2from llama_index.core.agent import ReActAgent3from llama_index.llms.openai_like import OpenAILike45def get_weather(city: str, unit: str = "celsius") -> dict:6 """Get current weather for a city."""7 return {"city": city, "temp": 22, "unit": unit, "condition": "Sunny"}89weather_tool = FunctionTool.from_defaults(fn=get_weather)1011llm = OpenAILike(12 model="openai/gpt-4o",13 api_base="http://148.153.38.18:3010/v1",14 api_key="$MYROUTER_API_KEY",15 is_chat_model=True,16 is_function_calling_model=True,17)1819agent = ReActAgent.from_tools([weather_tool], llm=llm, verbose=True)20response = agent.chat("What's the weather in Tokyo?")21print(response)Coding Tools
MyRouter drops into every popular AI coding assistant — point them at our base URL, paste your key, and keep using the workflow you already know.
Claude Code
Claude Code reads its settings from ~/.claude/settings.json (global) and .claude/settings.json (per-project). Set the Anthropic base URL and auth token inside the env block and the CLI will talk to MyRouter instead of api.anthropic.com.
~/.claude/settings.json— global config — applies to every project on this machine..claude/settings.json— checked into a repo — override the model or endpoint per project.- Use ANTHROPIC_MODEL / ANTHROPIC_SMALL_FAST_MODEL to pin the main and background models — any MyRouter model id works.
Model ids: Claude Code only sends the string you configure — you can route to non-Anthropic models (e.g. deepseek/deepseek-v3) as long as MyRouter knows the id.
Cursor
Cursor lets you override the OpenAI base URL from Settings → Models. After overriding, add any MyRouter model id to the model list and it becomes available in chat, Cmd-K, and Composer.
- Override the OpenAI base URL to MyRouter's /v1 endpoint — no plugin needed.
- Add your MyRouter key as the OpenAI API key and click Verify.
- Add model ids manually (e.g. openai/gpt-4o, anthropic/claude-sonnet-4-5) under Model Names.
Tab & Apply: Cursor's proprietary Tab autocomplete and "Apply" models stay on Cursor's servers — only chat, Cmd-K, and Composer route through MyRouter.
opencode
opencode (sst/opencode) is an open-source Claude Code alternative that talks to any OpenAI-compatible provider. Drop an opencode.json into your project and you're done.
- Declare MyRouter as a custom provider via @ai-sdk/openai-compatible.
- Reference your key with {env:MYROUTER_API_KEY} to keep it out of version control.
- List exactly the MyRouter model ids you want exposed in opencode's model picker.
Other Editors & CLIs
Anything that speaks the OpenAI Chat Completions protocol works the same way — set the base URL and key, pick a model id:
- Continue / Cline / Roo Code: Set OpenAI-compatible provider + base URL in the extension settings.
- Aider: aider --openai-api-base ${API_BASE_URL}/v1 --openai-api-key $MYROUTER_API_KEY --model openai/gpt-4o
- Zed / Windsurf: Configure a custom OpenAI provider in assistant settings with the MyRouter base URL.
Claude Code · ~/.claude/settings.json
1{2 "env": {3 "ANTHROPIC_BASE_URL": "http://148.153.38.18:3010",4 "ANTHROPIC_AUTH_TOKEN": "sk-myrouter-...",5 "ANTHROPIC_MODEL": "anthropic/claude-sonnet-4-5",6 "ANTHROPIC_SMALL_FAST_MODEL": "anthropic/claude-haiku-4-5"7 }8}Claude Code · .claude/settings.json (per project)
1{2 "env": {3 "ANTHROPIC_BASE_URL": "http://148.153.38.18:3010",4 "ANTHROPIC_AUTH_TOKEN": "sk-myrouter-...",5 "ANTHROPIC_MODEL": "deepseek/deepseek-v3",6 "ANTHROPIC_SMALL_FAST_MODEL": "anthropic/claude-haiku-4-5"7 }8}Claude Code · Run
1# save the JSON above, then just launch2claude34# verify the active endpoint5claude config list | grep ANTHROPIC_BASE_URLCursor · In-App Settings
1Cursor Settings → Models231. Scroll to "OpenAI API Key"42. Paste your MyRouter key: sk-myrouter-...53. Click "Override OpenAI Base URL"64. Enter: http://148.153.38.18:3010/v175. Click "Verify"86. Under "Model Names", click "+ Add model"9 and add any MyRouter model id, e.g.:10 - openai/gpt-4o11 - anthropic/claude-sonnet-4-512 - deepseek/deepseek-v3137. Enable the new model in the Models list.Cursor · Verify
1# In Cursor chat (⌘L / Ctrl+L)2# pick the custom model from the model picker,3# then send any prompt — a response confirms the4# key and base URL are wired up correctly.56> Explain this function in one sentence.opencode · opencode.json
1{2 "$schema": "https://opencode.ai/config.json",3 "provider": {4 "myrouter": {5 "npm": "@ai-sdk/openai-compatible",6 "name": "MyRouter",7 "options": {8 "baseURL": "http://148.153.38.18:3010/v1",9 "apiKey": "{env:MYROUTER_API_KEY}"10 },11 "models": {12 "openai/gpt-4o": { "name": "GPT-4o" },13 "anthropic/claude-sonnet-4-5": { "name": "Claude Sonnet 4.5" },14 "deepseek/deepseek-v3": { "name": "DeepSeek V3" }15 }16 }17 }18}opencode · Run
1export MYROUTER_API_KEY="sk-myrouter-..."23# place opencode.json in project root or ~/.config/opencode/4cd your-project5opencode67# pick myrouter/<model-id> in the model pickerPricing & Billing
MyRouter charges pay-as-you-go with no subscriptions, no minimums, and no markup on most models. You only pay for tokens you actually consume.
Pay-As-You-Go
Prepay credits and use them across every model. Credits never expire.
- No subscription or commitment.
- Same price as going directly to the provider for most models.
- Per-key spend limits to control costs.
Credits
Credits are denominated in USD. 1 credit = $1. Every API call deducts the exact USD cost of the tokens used.
Top Up
Add credits to your account from the dashboard using:
- Credit / debit card (Stripe)
- Wire transfer (minimum $1000)
- Crypto (USDC, ETH via Coinbase)
Billing Units
| Category | Unit |
|---|---|
| Chat / Embeddings | USD / 1M tokens |
| Image generation | USD / image |
| TTS | USD / 1M characters |
| Audio transcription | USD / minute |
| Web search | USD / result |
Per-Request Cost
Retrieve the exact cost of any past generation with GET /v1/generation.
Cost Calculation
1// openai/gpt-4o:2// input: $2.50 / 1M tokens3// output: $10.00 / 1M tokens4//5// Request uses 1,500 input tokens and 500 output tokens:6const cost =7 (1500 / 1_000_000) * 2.50 + // = $0.003758 (500 / 1_000_000) * 10.00; // = $0.0059// total: $0.00875Check Balance
1curl https://api.myrouter.ai/v1/credits \2 -H "Authorization: Bearer $MYROUTER_API_KEY"Privacy & Data
How MyRouter handles your prompts, completions, and personal data. Opt out of logging entirely with zero-data-retention mode.
Default Logging
By default, MyRouter logs only minimal metadata for billing and debugging:
- Token counts, latency, model, provider, timestamp
- Prompts and completions are NOT stored unless you explicitly opt in
- Error payloads may be retained for 24h for debugging
Per-Provider Data Collection
Some upstream providers log data regardless. Use provider.data_collection: "deny" to skip any provider that does not guarantee no retention.
Zero Data Retention Mode
Enable ZDR from the dashboard to drop all logs immediately. Billing metadata is tallied in memory and only the aggregate total is retained.
Compliance
- GDPR · CCPA
- SOC 2 Type II
- TLS 1.3 encryption in transit
- AES-256 encryption at rest for persistent data
For DPA requests or security audits contact privacy@myrouter.ai.
Deny Data Collection
1{2 "model": "openai/gpt-4o",3 "messages": [...],4 "provider": {5 "data_collection": "deny"6 }7}Zero Data Retention Mode
1// Dashboard setting:2// Privacy > Enable zero-data-retention mode3//4// All logs are dropped immediately.5// Generation stats endpoint will return 404.