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

Authentication

Inference keys and management keys are different keys

/api/v1 authenticates with exactly one thing: an Authorization: Bearer <key> header. No cookies, no query parameters, no api_key body field.

Authorization: Bearer sk-mo-v1-3f2a…

The two kinds of key

PrefixKindWhat it can do
sk-mo-v1-Inference keyCall models, read its own usage and balance
sk-mo-mgmt-v1-Management keyCreate, list, update and revoke inference keys

A key is <prefix> followed by 32 random bytes as 64 hex characters. The plaintext is never stored on the server — only sha256(full plaintext) and a masked display string (sk-mo-v1-3f2…a19). Once you leave the page that created it, the plaintext is gone.

Which key each path needs

PathKey required
POST /chat/completions, POST /completionsInference key
GET /models/userInference key
GET /generation, GET /key, GET /auth/key, GET /creditsInference or management key
GET/POST /keys, GET/PATCH/DELETE /keys/{hash}Management key only
GET /models, /models/count, /models/{author}/{slug}/endpoints, /providers, /datasets/*, /benchmarksNone

Paths that answer "is this key alive?" — /key, /credits — accept either kind. There is no reason to block an SDK's health check because of the key type. The paths that create and destroy other keys, /keys, accept management keys only.

Why management keys are separate

/api/v1 is an SDK surface. Mixing browser session cookies into it would open a CSRF surface. So the dashboard UI does not call /api/v1/keys; it uses a separate, session-authenticated dashboard API, and /api/v1 never looks at cookies at all. Both paths call the same service functions internally, so the key lifecycle rules exist in exactly one place.

You issue a management key yourself from the dashboard settings screen. See Management API keys.

When a key is rejected

Verification runs in the order below, and the order changes the answer — suspension is checked before expiry, so an expired suspended key gets 402/403 rather than 401. We answer "will topping up fix this?" first, because that is the question you actually have.

OrderConditionResponse
1Hash not found401 invalid_api_key
2Disabled or revoked401 invalid_api_key
3Suspended by the system for lack of credit402 insufficient_credits (with metadata.balance_krw)
4Suspended by an administrator403 key_suspended
5Past its expires_at401 expired_api_key
6Key kind does not match the path401 invalid_api_key

403 key_suspended is deliberately distinct from 402. A 402 clears when you top up; a 403 does not. The split exists so that the status code alone tells you what to do next.

A missing Authorization header, or one that is not in Bearer form, is also 401 invalid_api_key.

Checking a key

curl https://openrouter.myip.co.kr/api/v1/key \
  -H "Authorization: Bearer $MYIP_API_KEY"

A healthy key returns a body like this. Every amount is in won (₩).

json
{
  "data": {
    "label": "sk-mo-v1-3f2…a19",
    "name": "production",
    "limit": 100000,
    "usage": 25500,
    "limit_remaining": 74500,
    "limit_reset": "monthly",
    "is_management_key": false,
    "usage_daily": 1200,
    "usage_weekly": 9000,
    "usage_monthly": 25500
  }
}

The full field list is on GET /key.

Handling keys safely

  • Never ship a key in a browser bundle or a mobile app. Proxy through your own server.
  • Inject keys through the environment. Every example in these docs reads MYIP_API_KEY.
  • Use one key per purpose and give each a spend limit. When a key exceeds its limit, only that key stops, with 402 key_limit_exceeded (see Rate limits).
  • If a key leaks, revoke it. Revocation is permanent — it cannot be undone, and there is no API to undo it.

最后更新于 2026年9月5日