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.

POST/v1/chat/completions

Headers

Include these headers with every API request:

Authorizationstringrequired
Bearer sk-myrouter-xxxx — Your API key as a Bearer token. Required.
HTTP-Refererstring
Your site URL for ranking on the leaderboard. Optional.
X-Titlestring
Your app name for display on the leaderboard. Optional.

Response 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:

ReasonDescription
stopModel finished naturally or hit a stop sequence
lengthHit max_tokens limit
tool_callsModel invoked one or more tool calls
content_filterContent was filtered by moderation
errorAn error occurred during generation (streaming only)

Generation Stats

Query cost and token usage for a specific generation by its ID:

GET/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 1
6 max_tokens?: number;
7 top_p?: number; // 0-1
8 frequency_penalty?: number; // -2 to 2
9 presence_penalty?: number; // -2 to 2
10 stop?: string | string[];
11 tools?: Tool[];
12 tool_choice?: ToolChoice;
13 response_format?: ResponseFormat;
14 seed?: number;
15
16 // MyRouter-specific
17 models?: string[]; // fallback model list
18 route?: "fallback";
19 provider?: ProviderPreferences;
20}
21
22interface 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": false
17 }
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 OpenAI
2
3client = OpenAI(
4 base_url="http://148.153.38.18:3010/v1",
5 api_key="$MYROUTER_API_KEY",
6)
7
8response = client.chat.completions.create(
9 model="openai/gpt-4o",
10 messages=[
11 {"role": "user", "content": "Hello, MyRouter!"}
12 ],
13)
14
15print(response.choices[0].message.content)

Install SDK

1pip install openai

Authentication

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-xxxxxxxxxxxx

Security 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-Refererstring
Your site URL for ranking on the leaderboard. Optional.
X-Titlestring
Your app name for display on the leaderboard. Optional.

SDK Configuration

1from openai import OpenAI
2
3client = OpenAI(
4 base_url="http://148.153.38.18:3010/v1",
5 api_key=os.environ["MYROUTER_API_KEY"],
6)
7
8response = 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)
8
9for chunk in stream:
10 content = chunk.choices[0].delta.content
11 if content:
12 print(content, end="")

SSE Stream Format

1: MYROUTER PROCESSING
2
3data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
4
5data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"The"},"finish_reason":null}]}
6
7data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" capital"},"finish_reason":null}]}
8
9data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":8,"total_tokens":20}}
10
11data: [DONE]

Stream Cancellation

1stream = client.chat.completions.create(
2 model="openai/gpt-4o",
3 messages=[{"role": "user", "content": "Long story"}],
4 stream=True,
5)
6
7for chunk in stream:
8 content = chunk.choices[0].delta.content
9 if content and "stop_word" in content:
10 stream.close() # Cancel the stream
11 break
12 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: 1
Sampling temperature between 0 and 2. Lower values make output more focused and deterministic, higher values more creative and random.
top_pnumberDefault: 1
Nucleus sampling. Only consider tokens with cumulative probability above this threshold. Range: (0, 1]. Generally use temperature or top_p, not both.
top_kintegerDefault: 0
Only sample from the top K most likely tokens. Range: [1, Infinity). Not available for OpenAI models. Set to 0 to disable.
frequency_penaltynumberDefault: 0
Penalizes tokens based on their existing frequency in the text. Range: [-2, 2]. Positive values reduce repetition.
presence_penaltynumberDefault: 0
Penalizes tokens based on whether they appear in the text so far. Range: [-2, 2]. Positive values encourage topic diversity.
repetition_penaltynumberDefault: 1
Alternative repetition penalty. Range: (0, 2]. Values > 1 penalize repetition. Not available for OpenAI models.
min_pnumberDefault: 0
Minimum probability threshold relative to the top token. Range: [0, 1]. Tokens below min_p * top_token_prob are filtered.
top_anumberDefault: 0
Top-A sampling threshold. Range: [0, 1]. Tokens with probability below top_a * top_token_prob² are filtered.
seedinteger
Seed for deterministic sampling. Same seed + parameters should produce same output. Not guaranteed across providers.

Output Parameters

max_tokensinteger
Maximum number of tokens to generate. Range: [1, context_length). If not set, the model will generate until it stops naturally.
stopstring | array
Up to 4 sequences where the API will stop generating further tokens. The stop sequence is not included in the output.
response_formatobject
Force output format. {"type": "json_object"} for basic JSON mode, or {"type": "json_schema", ...} for strict schema enforcement.
logprobsboolean
Whether to return log probabilities of the output tokens.
top_logprobsinteger
Number of most likely tokens to return at each position. Range: [0, 20]. Requires logprobs: true.
logit_biasobject
JSON object mapping token IDs to bias values (-100 to 100). Modifies the likelihood of specified tokens appearing.

Advanced Parameters

toolsarray
List of tools the model may call. Each tool has a type ("function") and a function object with name, description, and parameters schema.
tool_choicestring | objectDefault: auto
Controls tool calling: "none" (never call), "auto" (model decides), "required" (must call one), or {"type": "function", "function": {"name": "..."}} for a specific function.
parallel_tool_callsbooleanDefault: true
Whether the model can make multiple tool calls in a single response.

Sampling 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": false
18 }
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

CodeMeaningSolution
400Bad RequestCheck request body format, parameters, and CORS
401UnauthorizedCheck your API key is valid and not expired
402Payment RequiredInsufficient credits — add funds to your account
403ForbiddenInput flagged by moderation — modify your content
408Request TimeoutReduce prompt length or increase timeout
429Too Many RequestsRate limited — slow down or upgrade your tier
502Bad GatewayModel is down or returned invalid response — retry
503Service UnavailableNo 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 only
2stream = 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)
10
11for chunk in stream:
12 if hasattr(chunk, "debug"):
13 print("Debug:", chunk.debug)
14 else:
15 content = chunk.choices[0].delta.content
16 if content:
17 print(content, end="")

Retry Example

1import time
2from openai import OpenAI, RateLimitError
3
4client = OpenAI(
5 base_url="http://148.153.38.18:3010/v1",
6 api_key="sk-myrouter-xxxx",
7)
8
9for 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 break
16 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:

GET/v1/key

Rate Limit Tiers

Limits are determined by your account tier:

TierRequests / minTokens / min
Free20200,000
Tier 1601,000,000
Tier 230010,000,000
Tier 31,00050,000,000
EnterpriseCustomCustom

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": false
12 }
13}

Response Headers

1X-RateLimit-Limit-Requests: 60
2X-RateLimit-Limit-Tokens: 1000000
3X-RateLimit-Remaining-Requests: 59
4X-RateLimit-Remaining-Tokens: 999500
5X-RateLimit-Reset-Requests: 1s
6X-RateLimit-Reset-Tokens: 30ms

Tool 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:

  1. You describe available tools as JSON schemas in the tools parameter.
  2. The model responds with either text or tool_calls containing function name and arguments.
  3. Your code executes each tool call and appends a tool message with the result.
  4. You call the API again — the model uses the results to produce the final answer or more tool calls.

Parameters

toolsarrayrequired
Array of tool definitions. Each has type: "function" and a function object with name, description, and JSON schema parameters.
tool_choicestring | objectDefault: auto
"none", "auto", "required" or a specific function object to force the model's choice.
parallel_tool_callsbooleanDefault: true
Whether the model can request multiple tool calls in a single turn.

Multi-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]
21
22response = 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?"}]
2
3while True:
4 response = client.chat.completions.create(
5 model="openai/gpt-4o",
6 messages=messages,
7 tools=tools,
8 )
9 msg = response.choices[0].message
10 messages.append(msg)
11
12 if not msg.tool_calls:
13 print(msg.content)
14 break
15
16 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.

namestringrequired
Identifier for the schema (alphanumeric, dashes, underscores).
strictbooleanDefault: false
When true, the model is guaranteed to follow the schema exactly.
schemaobjectrequired
Standard JSON Schema object describing the shape of the response.

Best 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)
9
10import json
11data = 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": False
19 }
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": false
21 }
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.urlstringrequired
HTTPS URL of a public image, or a base64 data URI.
image_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-mini
  • anthropic/claude-sonnet-4, anthropic/claude-opus-4
  • google/gemini-2.5-pro, google/gemini-2.5-flash
  • qwen/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 base64
2
3with open("cat.jpg", "rb") as f:
4 b64 = base64.b64encode(f.read()).decode()
5
6response = 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 levels
  • deepseek/deepseek-r1 — open-source reasoning model
  • anthropic/claude-opus-4 — via extended thinking
  • google/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_tokensinteger
Explicit cap on reasoning tokens. Takes precedence over effort.
reasoning.excludebooleanDefault: false
If true, reasoning is still used internally but not returned in the response.

Billing

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": False
10 }
11 }
12)
13
14print(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": false
7 }
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": 1191
14 }
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

ProviderCache WriteCache Read
Anthropic1.25x0.1x
OpenAI1x0.5x
DeepSeek1x0.1x
Google Gemini1x0.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": 1400
8 },
9 "cache_creation_input_tokens": 0,
10 "cache_read_input_tokens": 1400
11 }
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 )

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

•RAG — Retrieve relevant context for language model prompts
•Semantic Search — Find content by meaning, not just keywords
•Clustering — Group similar documents together
•Classification — Categorize text by comparing to labeled examples
•Deduplication — Detect near-duplicate content
•Anomaly Detection — Identify outliers in text data
POST/v1/embeddings

Available Models

ModelDimensionsMax Tokens
openai/text-embedding-3-small15368191
openai/text-embedding-3-large30728191
openai/text-embedding-ada-00215368191
cohere/embed-english-v3.01024512
cohere/embed-multilingual-v3.01024512

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)
5
6embedding = response.data[0].embedding
7print(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)
9
10for item in response.data:
11 print(f"[{item.index}] dims={len(item.embedding)}")

Semantic Search

1import numpy as np
2
3def cosine_similarity(a, b):
4 return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
5
6# Embed the query
7query_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].embedding
12
13# Compare against stored document embeddings
14for 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.

POST/v1/chat/completions

Request Body

modelstringrequired
Model ID, e.g. openai/gpt-4o, anthropic/claude-sonnet-4, deepseek/deepseek-chat
messagesarrayrequired
Array of message objects. Each has role ("system", "user", "assistant", "tool") and content (string or content parts array).
streambooleanDefault: false
Enable streaming via SSE. See Streaming.
temperaturenumberDefault: 1
Sampling temperature, 0 to 2.
max_tokensinteger
Maximum tokens to generate. Range: [1, context_length).
top_pnumberDefault: 1
Nucleus sampling threshold.
stopstring | array
Up to 4 stop sequences.
toolsarray
Tool definitions for function calling.
tool_choicestring | objectDefault: auto
Tool calling behavior: "none", "auto", "required", or specific function.
response_formatobject
Force JSON output. {"type": "json_object"} or JSON schema mode.
frequency_penaltynumberDefault: 0
Range: [-2, 2].
presence_penaltynumberDefault: 0
Range: [-2, 2].
seedinteger
Seed for deterministic output.

Provider Preferences

Control which providers handle your request with the provider parameter:

provider.orderstring[]
Ordered list of provider slugs, e.g. ["openai", "azure", "anthropic"]
provider.allow_fallbacksbooleanDefault: true
Allow backup providers when preferred ones are unavailable.
provider.require_parametersbooleanDefault: false
Only route to providers supporting all request parameters.
provider.data_collectionstring
Data retention policy: "deny" or "allow"
provider.quantizationsstring[]
Filter by quantization: int4, int8, fp8, fp16, bf16, etc.

Response

A successful response returns a chat completion object:

idstring
Unique identifier for the completion.
objectstring
Always "chat.completion" (or "chat.completion.chunk" for streaming).
modelstring
The model that generated the response.
choicesarray
Array of completion choices. Each contains index, message (role + content), and finish_reason.
usageobject
Token counts: prompt_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": 33
20 }
21}

POST /v1/completions

Legacy text completion endpoint for instruct models. Compatible with the old OpenAI /v1/completions shape.

POST/v1/completions

Legacy: For new projects, use the chat completions endpoint instead: /v1/chat/completions.

Request Body

modelstringrequired
Instruct model ID, e.g. openai/gpt-3.5-turbo-instruct.
promptstring | string[]required
Prompt string, or array of strings for batch.
max_tokensinteger
Maximum tokens to generate.
temperaturenumberDefault: 1
Sampling temperature.
top_pnumberDefault: 1
Nucleus sampling cutoff.
stopstring | string[]
Up to 4 stop sequences.
streambooleanDefault: false
Enable SSE streaming.
suffixstring
Text to append after generated tokens (for insertion-style tasks).
echobooleanDefault: false
If true, echo the prompt back in the response.

Request 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)
7
8print(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": 133
15 }
16}

GET /v1/models

Returns a list of all available models and their properties, including pricing, context length, and capabilities.

GET/v1/models

Query Parameters

categorystring
Filter by category: programming, roleplay, marketing, science, translation, etc.
supported_parametersstring
Filter by supported parameters, comma-separated. E.g. tools,response_format
output_modalitiesstringDefault: text
Filter by output modality: text, image, audio, embeddings, all

Model Object

Each model object in the response contains:

idstring
Unique identifier, e.g. openai/gpt-4o
namestring
Display name.
descriptionstring
Model description.
context_lengthinteger
Maximum context length in tokens.
pricingobject
Per-token costs: prompt, completion, request, image.
architectureobject
tokenizer, instruct_type, input_modalities, output_modalities.
top_providerobject
Best provider info: context_length, max_completion_tokens, is_moderated.
supported_parametersstring[]
List of supported request parameters.
knowledge_cutoffstring
ISO 8601 date of training data cutoff.

Request 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": true
26 },
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.

GET/v1/models/:author/:slug/endpoints

Path Parameters

authorstringrequired
Model author / provider slug, e.g. openai, anthropic
slugstringrequired
Model slug, e.g. gpt-4o, claude-sonnet-4

Response

Returns an array of endpoint objects for the specified model:

provider_namestring
Name of the provider, e.g. OpenAI, Azure
context_lengthinteger
Maximum context length for this endpoint.
max_completion_tokensinteger
Maximum completion tokens.
pricingobject
Per-token costs: prompt, completion.
quantizationstring
Model quantization: fp16, fp8, int8, int4, etc.
latency_last_30mobject
Latency in seconds: p50, p75, p90, p99.
throughput_last_30mobject
Throughput in tokens/sec: p50, p75, p90, p99.
uptime_last_30mnumber
Uptime percentage over the last 30 minutes.
statusinteger
0 = 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.85
24 },
25 "throughput_last_30m": {
26 "p50": 85,
27 "p75": 72,
28 "p90": 55,
29 "p99": 32
30 },
31 "uptime_last_30m": 99.8,
32 "status": 0
33 },
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.

GET/v1/providers

Response

Returns an array of provider objects:

namestring
Display name, e.g. OpenAI, Anthropic
slugstring
URL-safe identifier, e.g. openai, anthropic
headquartersstring
Country code, e.g. US, CN
datacentersstring[]
Datacenter locations, e.g. ["US", "EU", "APAC"]
privacy_policy_urlstring
Link to the provider's privacy policy.
terms_of_service_urlstring
Link to the provider's terms of service.
status_page_urlstring
Link to the provider's status page.

Request 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.

GET/v1/generation?id={GENERATION_ID}

Stats are available ~200ms after the request completes. Useful for analytics, cost attribution, and debugging.

Query Parameters

idstringrequired
The generation id returned from a previous chat/completions call.

Response

modelstring
The model that actually ran (may differ from requested when fallback triggered).
providerstring
The upstream provider that served the request.
tokens_prompt / tokens_completioninteger
Normalized token counts used for billing.
native_tokens_*integer
Raw provider-reported token counts (may differ due to tokenizer).
total_costnumber
Exact USD cost debited from your credits.
latency_msinteger
End-to-end latency in milliseconds.
cache_discountnumber
Savings from prompt caching, as a multiplier on input price.
finish_reasonstring
Finish reason — stop, length, tool_calls, content_filter, error.

Request 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": true
16 }
17}

GET /v1/credits

Query your current credit balance, usage, and rate limits. Safe to call frequently — cached briefly upstream.

GET/v1/credits

Response

total_creditsnumber
Total credits purchased (USD).
total_usagenumber
Credits consumed so far (USD).
rate_limitobject
Your current rate limit tier based on credits.
is_free_tierboolean
Whether you're on the free tier.

Surface 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": false
10 }
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.

POST/v1/images/generations

Request Body

modelstringrequired
openai/dall-e-3, black-forest-labs/flux-1.1-pro, stabilityai/sdxl
promptstringrequired
Text description of the desired image. Max 4000 characters.
sizestringDefault: 1024x1024
256x256, 512x512, 1024x1024, 1024x1792, 1792x1024
nintegerDefault: 1
Number of images to generate in one call. Range: [1, 10].
qualitystringDefault: 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"
seedinteger
Seed for deterministic generation (supported by FLUX and SDXL).

Supported Models

  • openai/dall-e-3, openai/dall-e-2
  • black-forest-labs/flux-1.1-pro, black-forest-labs/flux-schnell
  • stabilityai/stable-diffusion-3.5-large
  • google/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)
7
8print(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.

POST/v1/audio/speech

Request Body

modelstringrequired
openai/tts-1, openai/tts-1-hd, fishaudio/fish-speech-1.5
inputstringrequired
Text to synthesize. Max 4096 characters.
voicestringrequired
alloy, echo, fable, onyx, nova, shimmer
response_formatstringDefault: mp3
mp3, opus, aac, flac, wav, pcm
speednumberDefault: 1.0
Playback speed multiplier. Range: [0.25, 4.0].

Response

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)
8
9response.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.

POST/v1/audio/transcriptions

Content-Type: multipart/form-data

Request Body

filefilerequired
Audio file to transcribe. Formats: mp3, mp4, mpeg, mpga, m4a, wav, webm.
modelstringrequired
openai/whisper-1, deepgram/nova-2, fishaudio/sense-voice-small
languagestring
ISO-639-1 code (e.g. "en", "zh"). Improves accuracy and latency.
promptstring
Optional text to guide the style or spelling of the transcription.
response_formatstringDefault: json
json, text, srt, verbose_json, vtt
temperaturenumberDefault: 0
Sampling temperature for the decoder. Range: [0, 1].
timestamp_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 )
9
10print(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.23
13 }
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.

POST/v1/embeddings

Request Body

modelstringrequired
Embedding model ID, e.g. openai/text-embedding-3-small
inputstring | arrayrequired
Text to embed. Can be a string or array of strings for batch processing.
encoding_formatstringDefault: float
Encoding format: float or base64.
dimensionsinteger
Number of output dimensions. Only supported by text-embedding-3 models.

Response

objectstring
Always "list".
dataarray
Array of embedding objects, each with index and embedding (float array).
modelstring
The model used.
usageobject
Token counts: prompt_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)
6
7print(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": 9
14 }
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.

POST/v1/rerank

Use 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

modelstringrequired
cohere/rerank-v3.5, baai/bge-reranker-v2-m3
querystringrequired
Search query to rank documents against.
documentsstring[] | object[]required
Array of strings, or array of objects with a text field.
top_ninteger
Only return this many results. Defaults to all documents.
return_documentsbooleanDefault: false
If true, include the original document text in the response.
max_chunks_per_docintegerDefault: 10
Max chunks per long document (auto-chunked internally).

Response

resultsarray
Ordered array of ranked results with scores.
results[].indexinteger
Index of this result in the original documents array.
results[].relevance_scorenumber
Relevance score in [0, 1]. Higher is more relevant.

Request Example

1import requests
2
3response = 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 OpenAI
2
3client = OpenAI(
4 base_url="http://148.153.38.18:3010/v1",
5 api_key="$MYROUTER_API_KEY",
6)

OpenAI SDK · Tool Calling

1import json
2from openai import OpenAI
3
4client = OpenAI(
5 base_url="http://148.153.38.18:3010/v1",
6 api_key="$MYROUTER_API_KEY",
7)
8
9tools = [{
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}]
24
25def get_weather(city: str, unit: str = "celsius"):
26 return {"city": city, "temp": 22, "unit": unit, "condition": "Sunny"}
27
28messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
29
30resp = client.chat.completions.create(
31 model="openai/gpt-4o",
32 messages=messages,
33 tools=tools,
34 tool_choice="auto",
35)
36
37msg = resp.choices[0].message
38messages.append(msg)
39
40for 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 })
48
49final = 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 ChatOpenAI
2
3llm = 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 tool
2from langchain_openai import ChatOpenAI
3
4@tool
5def 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"}
8
9llm = ChatOpenAI(
10 model="openai/gpt-4o",
11 base_url="http://148.153.38.18:3010/v1",
12 api_key="$MYROUTER_API_KEY",
13)
14
15llm_with_tools = llm.bind_tools([get_weather])
16messages = [("user", "What's the weather in Tokyo?")]
17
18ai_msg = llm_with_tools.invoke(messages)
19messages.append(ai_msg)
20
21for call in ai_msg.tool_calls:
22 tool_msg = get_weather.invoke(call)
23 messages.append(tool_msg)
24
25final = llm_with_tools.invoke(messages)
26print(final.content)

Vercel AI SDK · Setup

1import { createOpenAI } from "@ai-sdk/openai";
2import { generateText } from "ai";
3
4const myrouter = createOpenAI({
5 baseURL: "http://148.153.38.18:3010/v1",
6 apiKey: process.env.MYROUTER_API_KEY,
7});
8
9const { 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";
4
5const myrouter = createOpenAI({
6 baseURL: "http://148.153.38.18:3010/v1",
7 apiKey: process.env.MYROUTER_API_KEY,
8});
9
10const { text, toolResults } = await generateText({
11 model: myrouter("openai/gpt-4o"),
12 maxSteps: 5, // multi-turn tool loop
13 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});
30
31console.log(text);

LlamaIndex · Setup

1from llama_index.llms.openai_like import OpenAILike
2
3llm = 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 FunctionTool
2from llama_index.core.agent import ReActAgent
3from llama_index.llms.openai_like import OpenAILike
4
5def 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"}
8
9weather_tool = FunctionTool.from_defaults(fn=get_weather)
10
11llm = 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)
18
19agent = 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 launch
2claude
3
4# verify the active endpoint
5claude config list | grep ANTHROPIC_BASE_URL

Cursor · In-App Settings

1Cursor Settings → Models
2
31. 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/v1
75. Click "Verify"
86. Under "Model Names", click "+ Add model"
9 and add any MyRouter model id, e.g.:
10 - openai/gpt-4o
11 - anthropic/claude-sonnet-4-5
12 - deepseek/deepseek-v3
137. 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 the
4# key and base URL are wired up correctly.
5
6> 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-..."
2
3# place opencode.json in project root or ~/.config/opencode/
4cd your-project
5opencode
6
7# pick myrouter/<model-id> in the model picker

Pricing & 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

CategoryUnit
Chat / EmbeddingsUSD / 1M tokens
Image generationUSD / image
TTSUSD / 1M characters
Audio transcriptionUSD / minute
Web searchUSD / 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 tokens
3// output: $10.00 / 1M tokens
4//
5// Request uses 1,500 input tokens and 500 output tokens:
6const cost =
7 (1500 / 1_000_000) * 2.50 + // = $0.00375
8 (500 / 1_000_000) * 10.00; // = $0.005
9// total: $0.00875

Check 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 mode
3//
4// All logs are dropped immediately.
5// Generation stats endpoint will return 404.