← mrnine.net

API Gateway docs

OpenAI-compatible. Endpoint: https://api.mrnine.net/v1. Key dạng sk-mrnine-*, tạo trong Dashboard.

Endpoints

  • POST /v1/responses — chuẩn mới, dùng bởi Codex CLI (wire_api = "responses").
  • POST /v1/chat/completions — OpenAI SDK / Cursor / Claude Code / mọi client OpenAI cũ. Hỗ trợ stream=true.
  • GET /v1/models — list model active.
  • GET /v1/usage/me — balance + usage 30 ngày.
  • GET /health — public, không cần auth.

Models đang bật (1)

claude-opus-4-8

curl — chat completions stream

bashcurl -N https://api.mrnine.net/v1/chat/completions \
  -H "Authorization: Bearer sk-mrnine-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "messages": [{"role":"user","content":"đếm từ 1 đến 5"}],
    "stream": true
  }'

Python — OpenAI SDK

pythonfrom openai import OpenAI

client = OpenAI(
    base_url="https://api.mrnine.net/v1",
    api_key="sk-mrnine-...",
)

# Chat
r = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "hi"}],
    stream=True,
)
for chunk in r:
    print(chunk.choices[0].delta.content or "", end="")

# Responses (mới — multi-turn server-side)
r = client.responses.create(model="gpt-5.4", input="hi")
print(r.output_text)

Codex CLI

Sửa ~/.codex/config.toml:

tomlmodel_provider = "MrNine"
model = "gpt-5.4"
review_model = "gpt-5.4"
model_reasoning_effort = "xhigh"
model_context_window = 1000000

[model_providers.MrNine]
name = "MrNine"
base_url = "https://api.mrnine.net"
wire_api = "responses"
requires_openai_auth = true

Set env trước khi chạy:

bashexport OPENAI_API_KEY=sk-mrnine-...

Cursor / Claude Code / SDK khác

Mọi client OpenAI-compatible đều dùng được — chỉ cần cấu hình:

  • Base URL: https://api.mrnine.net/v1
  • API key: sk-mrnine-* của bạn
  • Model: lấy từ /v1/models hoặc trang Dashboard

Function calling (tools)

Pass-through hoàn toàn — gateway forward field tools tool_choice sang upstream. Phía model trả tool_calls, bạn execute tool và gửi roletool message kèm tool_call_id.

pythonfrom openai import OpenAI
import json

client = OpenAI(base_url="https://api.mrnine.net/v1", api_key="sk-mrnine-...")

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Lấy thời tiết hiện tại theo thành phố",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string"},
                "unit": {"type": "string", "enum": ["c", "f"], "default": "c"},
            },
            "required": ["city"],
        },
    },
}]

messages = [{"role": "user", "content": "Trời Hà Nội hôm nay thế nào?"}]
r = client.chat.completions.create(model="gpt-5.4", messages=messages, tools=tools)
msg = r.choices[0].message
messages.append(msg)

if msg.tool_calls:
    for tc in msg.tool_calls:
        args = json.loads(tc.function.arguments)
        result = lookup_weather(args["city"])  # bạn tự implement
        messages.append({
            "role": "tool",
            "tool_call_id": tc.id,
            "content": json.dumps(result),
        })
    r2 = client.chat.completions.create(model="gpt-5.4", messages=messages, tools=tools)
    print(r2.choices[0].message.content)

tool_choice có thể là "auto", "required", "none", hoặc {"type":"function","function":{"name":"..."}} để ép gọi tool cụ thể.

Embeddings

pythonr = client.embeddings.create(
    model="text-embedding-3-small",
    input=["Hello", "Xin chào"],
)
for d in r.data:
    print(d.index, len(d.embedding))

Audio transcription

pythonwith open("audio.mp3", "rb") as f:
    r = client.audio.transcriptions.create(
        model="whisper-1",
        file=f,
        language="vi",
    )
print(r.text)

Image generation

pythonr = client.images.generate(
    model="dall-e-3",
    prompt="A red panda coding at a desk, studio ghibli style",
    size="1024x1024",
    n=1,
)
print(r.data[0].url)

Image edit (inpainting)

pythonr = client.images.edit(
    model="dall-e-2",
    image=open("input.png", "rb"),
    mask=open("mask.png", "rb"),
    prompt="Replace masked area with a sunflower field",
    n=1,
    size="1024x1024",
)
print(r.data[0].url)

Image variations

pythonr = client.images.create_variation(
    model="dall-e-2",
    image=open("input.png", "rb"),
    n=2,
    size="1024x1024",
)
for d in r.data:
    print(d.url)

Moderation (free)

pythonr = client.moderations.create(
    model="omni-moderation-latest",
    input="Some text to check",
)
print(r.results[0].flagged, r.results[0].categories)

Rerank (Cohere/Jina format)

bashcurl https://api.mrnine.net/v1/rerank \
  -H "Authorization: Bearer sk-mrnine-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "rerank-multilingual-v3",
    "query": "AI gateway giá rẻ",
    "documents": [
      "MrNine bán API key OpenAI compatible",
      "Hôm nay trời mưa",
      "VietQR thanh toán nhanh"
    ],
    "top_n": 2
  }'

Text-to-speech

pythonr = client.audio.speech.create(
    model="tts-1",
    voice="alloy",
    input="Xin chào, tôi là MrNine.",
)
r.stream_to_file("hello.mp3")

Batch API (50% rẻ hơn)

Upload .jsonl input → tạo batch → poll status → download output. Hoàn thành trong 24h, giá rẻ ~50%.

python# 1. Upload input
f = client.files.create(
    file=open("requests.jsonl", "rb"),
    purpose="batch",
)

# 2. Tạo batch
batch = client.batches.create(
    input_file_id=f.id,
    endpoint="/v1/chat/completions",
    completion_window="24h",
)
print(batch.id, batch.status)

# 3. Poll status
batch = client.batches.retrieve(batch.id)
if batch.status == "completed":
    out = client.files.content(batch.output_file_id)
    print(out.text)

Rate limit & quota

  • Default RPM = 60 / phút, TPM = 200K tokens / phút mỗi key.
  • Daily token cap = 1M tokens / key (admin tăng theo nhu cầu).
  • Vượt → 429 + body OpenAI-style error.
  • Hết balance → 402 Payment Required, kèm link tới trang nạp.

Headers ghi log

  • X-MrNine-Request-Id — request id (mỗi request) để tra log khi hỗ trợ.
  • X-Accel-Buffering: no — server-side, đảm bảo SSE không buffer qua reverse proxy.

Error format

json{
  "error": {
    "message": "Insufficient balance. Please top up at https://mrnine.net/dashboard/billing",
    "type": "insufficient_balance",
    "code": "balance_required"
  }
}

Hỗ trợ

Hỏi nhanh: hello@mrnine.net. Khi báo lỗi, kèm X-MrNine-Request-Id để tra cứu.