계정
속도 제한
요금제별 분당 요청 수와 키별 RPM 및 일일 USD 한도, 요청 한도 헤더, Idempotency-Key를 이용한 안전한 재시도, 429 응답을 만났을 때의 대처 방법을 코드 예제와 함께 정리했습니다. 업스트림 한도와 일일 지출 한도 초과 상황도 설명합니다.
속도 제한은 잔액과 서비스를 보호합니다. 한도는 API 키별 분당 요청 수(RPM)로 계산되며, 키에 일일 USD 지출 한도를 추가로 설정할 수도 있습니다.
요금제별 한도
| 요금제 | 분당 요청 수 |
|---|---|
| Free | 5 |
| Pro | 100 |
| Team | 3,000 |
| Enterprise | 3,000+ |
한도를 높이려면 요금 페이지에서 업그레이드하세요.
키별 한도
API 키에서 키를 만들거나 수정할 때 다음을 설정할 수 있습니다.
| 한도 | 효과 |
|---|---|
| RPM 한도 | 이 키의 분당 요청 수를 제한합니다. 실제 적용되는 한도는 키 한도와 요금제 한도 중 더 낮은 값입니다. |
| 일일 USD 한도 | 키가 오늘(UTC) 이 금액만큼 사용하면, 다음 날까지 이후 요청은 429 daily_limit_reached를 반환합니다. |
| 모델 허용 목록 | 이 키로는 목록에 있는 모델 ID만 사용할 수 있으며, 그 밖의 모델은 403 model_not_allowed를 반환합니다. |
RPM 윈도는 1분이며 키별로 계산됩니다. 따라서 앱마다 별도의 키를 쓰면 한도를 공유하지 않습니다. 다만 모든 키는 여전히 요금제 한도의 적용을 받습니다.
요청 한도 헤더
모든 생성 응답(성공 또는 오류)에 현재 상태가 담겨 있어 한도에 닿기 전에 속도를 줄일 수 있습니다:
| 헤더 | 의미 |
|---|---|
X-RateLimit-Limit | 이 키의 현재 1분 창에서 허용되는 요청 수. |
X-RateLimit-Remaining | 창에 남은 요청 수. |
X-RateLimit-Reset | 창이 초기화되기까지 남은 초. |
브라우저 클라이언트도 읽을 수 있습니다(Access-Control-Expose-Headers에 포함).
급증과 동시 실행
한도를 넘은 요청은 바로 거부되지 않고 대기열에서 기다리다가 1분 창이 비는 즉시 시작됩니다. 계정당 최대 10개 요청이 동시에 실행되며, 나머지는 하나가 끝날 때까지 기다립니다. 요청이 시작되기 전에 예상 최대 비용이 실행 중인 요청의 비용과 함께 잔액에서 예약되므로, 병렬 요청이 잔액보다 많이 사용할 수 없습니다. 60초 안에 시작하지 못한 요청은 Retry-After와 함께 429(rate_limited 또는 concurrency_limit)를 반환하고, 비용이 더 이상 잔액에 맞지 않는 요청은 402 insufficient_balance를 반환합니다.
Idempotency-Key로 안전하게 재시도
네트워크 오류 뒤에는 요청이 도착했는지 알기 어렵습니다. Idempotency-Key 헤더(UUID 같은 최대 120자의 고유 문자열)를 보내고 같은 키로 재시도하세요. 첫 요청이 이미 모델로 전달됐다면 재시도는 작업을 두 번 실행하고 과금하는 대신 409 idempotency_conflict를 반환합니다. 첫 요청이 모델에 닿기 전에 실패했다면 키가 해제되어 재시도가 정상 실행됩니다. 키는 계정당 24시간 동안 한 번 쓸 수 있습니다.
curl https://api14.com/api/v1/images/generations \
-H "Authorization: Bearer $API14_KEY" \
-H "Idempotency-Key: 6f1c2a3e-order-1842" \
-H "Content-Type: application/json" \
-d '{"model": "black-forest-labs/flux-3-image", "prompt": "a red bicycle"}'
한도에 도달했을 때
요청이 너무 많은 경우
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
"error": {
"message": "Rate limit of 5 requests per minute exceeded.",
"type": "rate_limit_error",
"code": "rate_limited"
}
}
Retry-After에 표시된 초만큼 기다린 뒤 재시도하세요. 공식 OpenAI SDK는 429 응답을 백오프와 함께 자동으로 재시도합니다(기본 2회, maxRetries / max_retries로 설정 가능).
일일 지출 한도
{
"error": {
"message": "This API key reached its daily spend limit.",
"type": "rate_limit_error",
"code": "daily_limit_reached"
}
}
다음 UTC 날짜가 될 때까지는 재시도해도 소용없습니다. 예상된 트래픽이라면 API 키에서 키의 일일 한도를 높이거나 제거하세요.
업스트림 한도
제공업체에는 자체 한도가 있으며, :free 모델 변형은 더 엄격합니다. 제공업체가 요청에 속도 제한을 걸면 그 429가 그대로 전달됩니다. 모델 폴백 또는 제공업체 라우팅을 사용해 여러 제공업체로 부하를 분산하세요.
코드에서 한도 처리하기
Retry-After를 따르고, 지수 백오프와 지터를 적용해 재시도하세요.rate_limited(나중에 재시도)와daily_limit_reached,insufficient_balance(재시도해도 소용없음)를 구분하세요.- 백그라운드 작업은 한꺼번에 실행하지 말고 큐에 넣으세요.
- 긴 응답은 스트리밍하세요. 스트리밍 요청도 요청 1건으로 계산됩니다.
import time
from openai import OpenAI, RateLimitError
client = OpenAI(base_url="https://api14.com/api/v1", api_key="sk-api14-...", max_retries=0)
for attempt in range(5):
try:
r = client.chat.completions.create(model="openai/gpt-5-mini", messages=[{"role": "user", "content": "Hi"}])
break
except RateLimitError as e:
if e.code == "daily_limit_reached":
raise
time.sleep(int(e.response.headers.get("retry-after", 2 ** attempt)))
모든 상태 코드는 오류를 참고하세요.