사용 한도와 402

잔액이 떨어지면 무슨 일이 일어나는가

MyIP OpenRouter 에는 두 종류의 한도가 있습니다. 얼마나 쓸 수 있는가(크레딧)와 얼마나 자주 부를 수 있는가(요청 빈도)입니다. 전자는 402, 후자는 429 로 돌아옵니다.

한도무엇을 제한하나오류어디서 확인하나
계정 잔액계정 전체가 쓸 수 있는 금액402 insufficient_creditsGET /api/v1/credits
키별 한도개별 API 키가 쓸 수 있는 금액402 key_limit_exceededGET /api/v1/keylimit_remaining
요청 빈도초당 요청 수429 rate_limit_exceeded응답의 Retry-After

지금 한도를 확인하기

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

응답의 주요 필드입니다. 금액은 전부 원(KRW) 입니다.

limitnumber | null

이 키에 설정된 사용 한도. null 이면 무제한입니다.

limit_remainingnumber | null

남은 한도. limitnull 이면 이 값도 null 입니다.

limit_resetstring | null

한도가 초기화되는 주기. never · daily · weekly · monthly 중 하나이거나 null 입니다.

usagenumber

현재 한도 주기 안에서 이 키가 쓴 금액. limit_resetnever 이거나 null 이면 전체 누적액입니다.

usage_daily / usage_weekly / usage_monthly

오늘·이번 주·이번 달 사용액. 경계는 Asia/Seoul 기준입니다.

계정 전체 잔액은 별도 엔드포인트입니다.

bash
curl https://openrouter.myip.co.kr/api/v1/credits \
  -H "Authorization: Bearer $MYIP_API_KEY"
json
{ "data": { "total_credits": 11000, "total_usage": 42.317 } }

잔액 = total_credits - total_usage 입니다.

402 — 크레딧 부족

요청을 받으면 업스트림에 보내기 전에 잔액을 먼저 확인합니다.

json
{
  "error": {
    "code": 402,
    "message": "크레딧이 부족합니다.",
    "metadata": { "error_type": "insufficient_credits", "balance_krw": "-5000.000000" }
  }
}

5,000원의 완충 구간

잔액이 정확히 0이 되는 순간 바로 막지 않습니다. -5,000원까지는 요청을 통과시킵니다.

이 완충 구간은 스트리밍 때문에 있습니다. 여러 스트리밍 요청이 동시에 잔액 검사를 통과한 뒤 각자 끝나면서 정산되면, 마지막 몇 건이 잔액을 잠깐 음수로 만들 수 있습니다. 그 초과분을 흡수하는 값입니다.

경계는 배타적입니다. 잔액이 -5000 이하이면 이미 완충을 다 쓴 것이므로 새 요청이 402 로 거절됩니다.

잔액 0 이하 → 키 자동 정지

정산 직후 잔액이 0 이하가 되면 그 계정의 활성 키 전부suspended_no_credit 으로 자동 정지됩니다. 이 상태의 키로 요청하면 402 insufficient_credits 입니다.

충전에 성공하면 자동으로 다시 활성화됩니다. 키를 새로 만들 필요가 없습니다.

402 를 푸는 방법

  1. /settings/credits 에서 충전합니다. 잔액이 양수가 되는 순간 자동 정지된 키가 되살아납니다.
  2. 키별 한도에 걸린 것이라면(key_limit_exceeded) /settings/keys 에서 한도를 올리거나, limit_reset 주기가 지나기를 기다립니다.
  3. 미리 감시합니다 — GET /api/v1/keylimit_remainingGET /api/v1/credits 를 주기적으로 확인하세요.

402 인데 충전해도 안 풀린다면

세 가지 키 상태를 구분해야 합니다.

키 상태누가 걸었나누가 푸나응답
suspended_no_credit시스템 (잔액 0 이하)충전하면 자동 복구402 insufficient_credits
suspended_admin관리자관리자만403 key_suspended
revoked사용자 또는 관리자아무도 풀 수 없음 (영구)401 invalid_api_key

403 key_suspended 를 받았다면 잔액과 무관합니다. 충전해도 풀리지 않으니 문의해 주세요. 폐기(revoked)한 키는 되살릴 수 없으므로 새 키를 발급하셔야 합니다.

429 — 요청이 너무 잦음

요청 빈도 제한은 IP 주소 단위로 걸립니다. 계정이나 키를 나눠도 같은 IP 라면 같은 한도를 공유합니다. 아주 심하게 초과하는 트래픽은 애플리케이션에 닿기 전에 리버스 프록시가 먼저 끊습니다 — 이때는 JSON 이 아니라 프록시의 오류 페이지가 돌아옵니다.

애플리케이션이 직접 거절할 때는 다음 형식입니다.

json
{
  "error": {
    "code": 429,
    "message": "요청이 너무 잦습니다. 잠시 후 다시 시도하세요.",
    "metadata": { "error_type": "rate_limit_exceeded", "retry_after_sec": 60 }
  }
}

metadata.retry_after_sec 가 있으면 응답에 Retry-After 헤더도 함께 나갑니다. 지수 백오프로 재시도하되 이 값을 우선 존중하세요.

업스트림 provider 가 자기 쪽 한도에 걸려 429 를 준 경우에는 502 provider_error 로 감싸 metadata.provider_code 에 원래 코드를 실어 보냅니다. 이때는 모델 폴백 이나 Provider 라우팅 으로 다른 후보를 태우는 편이 낫습니다.

스트리밍 도중에 한도에 걸리면

첫 바이트를 보낸 뒤에는 HTTP 상태를 바꿀 수 없습니다. 그래서 오류가 SSE 이벤트로 도착합니다.

text
data: {"id":"gen-01J...","object":"chat.completion.chunk","created":1788000000,"model":"lgai/exaone-4.0-32b","provider":"MyIP Local","error":{"code":502,"message":"upstream disconnected","metadata":{"error_type":"provider_error"}},"choices":[{"index":0,"delta":{"content":""},"finish_reason":"error"}]}

스트림을 읽는 코드는 각 청크에 error 키가 있는지, finish_reason"error" 인지 확인해야 합니다. 자세한 예제는 스트리밍 에 있습니다.

그 밖의 한도

항목
업스트림 응답 타임아웃600초 (초과 시 408 timeout)
요청 본문 크기25MB
로컬 모델 기동 대기 예산기본 25초 (초과 시 다음 후보로 폴백, 폴백이 없으면 503 model_loading)
대기 중인 결제 주문계정당 10건

503 model_loading 은 로컬 GPU 모델이 아직 올라오는 중일 때 나옵니다. metadata.retry_after_sec 만큼 기다렸다가 다시 부르면 대개 성공합니다. 콜드 스타트에 대한 설명은 자주 묻는 질문 을 보세요.

오류 본문 형식

모든 오류는 같은 형식입니다. HTTP 상태 코드와 error.code 는 항상 같습니다.

json
{
  "error": {
    "code": 402,
    "message": "사람이 읽을 수 있는 설명",
    "metadata": { "error_type": "insufficient_credits" }
  }
}

프로그램은 error.metadata.error_type 으로 분기하세요. message 는 사람이 읽으라고 있는 것이고 문구가 바뀔 수 있습니다. 전체 목록은 오류와 디버깅 에 있습니다.

마지막 수정 2026. 9. 5.