本文档尚未翻译成简体中文,现显示英文原文。

OpenAI SDK

Change one base URL and you are done

The /api/v1 surface of MyIP OpenRouter is compatible with the OpenAI Chat Completions API. If you already have code written against the official OpenAI SDK, changing the base URL and the API key is enough.

ItemValue
Base URLhttps://openrouter.myip.co.kr/api/v1
AuthAuthorization: Bearer sk-mo-v1-… (the SDK sets it from api_key)
Environment variableMYIP_API_KEY
Example modelsgoogle/gemma-4-26b-a4b, lgai/exaone-4.0-32b

Create a key at /settings/keys. Inference keys start with sk-mo-v1-.

Python

bash
pip install openai
export MYIP_API_KEY="sk-mo-v1-..."
python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://openrouter.myip.co.kr/api/v1",
    api_key=os.environ["MYIP_API_KEY"],
    default_headers={
        # Optional. Lets you break usage down per app in the dashboard.
        "HTTP-Referer": "https://example.com",
        "X-Title": "My Example App",
    },
)

completion = client.chat.completions.create(
    model="google/gemma-4-26b-a4b",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "What is the capital of South Korea?"},
    ],
    temperature=0.7,
    max_tokens=256,
)

print(completion.choices[0].message.content)
print(completion.usage)

TypeScript / JavaScript

bash
npm install openai
export MYIP_API_KEY="sk-mo-v1-..."
typescript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://openrouter.myip.co.kr/api/v1',
  apiKey: process.env.MYIP_API_KEY,
  defaultHeaders: {
    'HTTP-Referer': 'https://example.com',
    'X-Title': 'My Example App',
  },
});

const completion = await client.chat.completions.create({
  model: 'google/gemma-4-26b-a4b',
  messages: [
    { role: 'system', content: 'You are a concise assistant.' },
    { role: 'user', content: 'What is the capital of South Korea?' },
  ],
  temperature: 0.7,
  max_tokens: 256,
});

console.log(completion.choices[0]?.message.content);
console.log(completion.usage);

Streaming

Just set stream. You do not need to pass stream_options.include_usagewe always request usage from the upstream on your behalf.

python
stream = client.chat.completions.create(
    model="lgai/exaone-4.0-32b",
    messages=[{"role": "user", "content": "Write a short poem."}],
    stream=True,
)

cost_krw = None
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage is not None:
        # The final usage chunk carries what this request cost, in KRW.
        cost_krw = getattr(chunk.usage, "cost", None) or chunk.usage.model_extra.get("cost")

print(f"\ncost: {cost_krw} KRW")
typescript
const stream = await client.chat.completions.create({
  model: 'lgai/exaone-4.0-32b',
  messages: [{ role: 'user', content: 'Write a short poem.' }],
  stream: true,
});

let costKrw: number | undefined;
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
  const usage = chunk.usage as { cost?: number } | undefined;
  if (usage?.cost !== undefined) costKrw = usage.cost;
}
console.log(`\ncost: ${costKrw} KRW`);

Reading the cost headers

Non-streaming responses carry the cost and the post-settlement balance in headers. All amounts are in Korean won (KRW).

HeaderMeaning
X-MyIP-Cost-KRWWhat this request cost (non-streaming only)
X-MyIP-Credit-BalanceBalance after settlement (non-streaming only)
X-MyIP-CurrencyAlways KRW
X-MyIP-ModelThe model that actually answered
X-MyIP-ProviderThe provider that answered
X-MyIP-Generation-IdThe id to pass to GET /api/v1/generation
python
raw = client.chat.completions.with_raw_response.create(
    model="google/gemma-4-26b-a4b",
    messages=[{"role": "user", "content": "Hello"}],
)

print(raw.headers["x-myip-cost-krw"], raw.headers["x-myip-currency"])
print(raw.headers["x-myip-generation-id"])

completion = raw.parse()
print(completion.choices[0].message.content)
typescript
const { data, response } = await client.chat.completions
  .create({
    model: 'google/gemma-4-26b-a4b',
    messages: [{ role: 'user', content: 'Hello' }],
  })
  .withResponse();

console.log(response.headers.get('x-myip-cost-krw'));
console.log(response.headers.get('x-myip-generation-id'));
console.log(data.choices[0]?.message.content);

Streaming responses cannot carry the cost in a header, because headers go out before the first byte. Use the usage chunk above, or query GET /api/v1/generation?id=… afterwards.

Model fallbacks

Our extension: send a models array and we try them in order. The OpenAI SDK does not know the field, so pass it through extra_body in Python.

python
completion = client.chat.completions.create(
    model="lgai/exaone-4.0-32b",
    messages=[{"role": "user", "content": "Hello"}],
    extra_body={"models": ["lgai/exaone-4.0-32b", "google/gemma-4-26b-a4b"]},
)

See Model fallbacks.

What does not work

Not every part of the OpenAI SDK maps onto our service. These return 404 not_supported:

  • client.embeddings.*
  • client.images.*, client.audio.*
  • client.responses.* (the Responses API)
  • client.batches.*, client.files.*

The full list and the response shape are in Unsupported endpoints.

client.chat.completions.*, client.completions.*, and client.models.list() all work.

最后更新于 2026年9月5日