لم تُترجَم هذه الصفحة إلى العربية بعد. يتم عرض النص الإنجليزي الأصلي.
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
| Prefix | Kind | What it can do |
|---|---|---|
sk-mo-v1- | Inference key | Call models, read its own usage and balance |
sk-mo-mgmt-v1- | Management key | Create, 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
| Path | Key required |
|---|---|
POST /chat/completions, POST /completions | Inference key |
GET /models/user | Inference key |
GET /generation, GET /key, GET /auth/key, GET /credits | Inference or management key |
GET/POST /keys, GET/PATCH/DELETE /keys/{hash} | Management key only |
GET /models, /models/count, /models/{author}/{slug}/endpoints, /providers, /datasets/*, /benchmarks | None |
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.
| Order | Condition | Response |
|---|---|---|
| 1 | Hash not found | 401 invalid_api_key |
| 2 | Disabled or revoked | 401 invalid_api_key |
| 3 | Suspended by the system for lack of credit | 402 insufficient_credits (with metadata.balance_krw) |
| 4 | Suspended by an administrator | 403 key_suspended |
| 5 | Past its expires_at | 401 expired_api_key |
| 6 | Key kind does not match the path | 401 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 (₩).
{
"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 402key_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.
آخر تحديث ٠٥/٠٩/٢٠٢٦