ブログ/developers·2026年8月31日·2分·執筆:eroqチーム
AI動画APIのレート制限を解説:上限、倍率、リトライの考え方
eroqのキーごと・1分あたりの上限、プランの倍率とメンバーごとの割り当てによる変化、そして429を受けたときの正しいバックオフ方法を解説します。
レート制限は、APIのなかでも普段は気にしない部分です。ところがある火曜日の午後、バッチ処理と製品のローンチが同じ1分間に重なり、すべてのリクエストが429を返し始めます。そこで初めて、自分のリトライ処理がループの中で1秒のsetTimeoutを回しているだけだと気づくのです。これはバックオフではありません。同じ殺到を、少しゆっくりしたテンポで繰り返しているだけです。
この記事では、eroqの制限がどう計算されるかを数値が適用される順に説明し、制限に達したときにも行儀よく振る舞うクライアントの書き方を紹介します。
基本の上限:キーごと、1分あたり
数値は3つです。APIキーごとに、スライドする60秒のウィンドウで数えられます。
- チャット:1分あたり60リクエスト。
POST /v1/chat/completionsが対象で、ストリーミングの有無は問いません。SSEストリームはトークンごとではなく、開いた時点で1回と数えられます。 - 画像:1分あたり20リクエスト。4枚をまとめて生成する1回の呼び出しは、1リクエストと数えられます。
- 動画と音声:それぞれ1分あたり6リクエスト。
1分あたり6件の動画リクエストは少なく見えますが、動画リクエストとは何かを思い出してください。それはレンダリングそのものではなく、ジョブの送信です。POST /v1/videos/generationsはすぐにジョブIDを返し、クリップは数分後に届きます。つまり1分に6件の送信とは、1分に6本の新しいレンダリングを始めるということで、これはかなりの制作量です。エンドポイントの完全なリファレンスは/docs/videoにあります。
単位に注意してください。アカウントごとではなくキーごとです。キーが2つあれば、ウィンドウも独立して2つになります。パイプラインごとにキーを1つ発行するよう勧めるのはこのためです。ステージングで暴走したループが制限をかけるのは、ステージングだけで済みます。
プランの倍率
有効なプランがあると、ワークスペース内のすべてのキーで、これらの基本上限がそれぞれ倍率分だけ引き上げられます。
- プランなし・Hobby:1×
- Creator:2×
- Studio:4×
- Team:6×
- Agency:8×
つまり動画の送信は1分あたり6件から、Studioでは24件、Agencyでは48件に増え、チャットは60件から240件、480件になります。キーの数も同時に増えます(Hobbyは10個、Creatorは20個、Studioは50個、Teamは100個、Agencyは200個)。そのため大きなプランでの実質的な上限は、倍率に、運用するつもりのキーの数を掛けたものになります。一覧表は/pricingにあります。
さらに、メンバーごとの割り当て
ワークスペースの中では、メンバーのロールによって、そのメンバーのキーが使える枠が絞られます。「開発者」と「管理者」はプランの枠をすべて使えます。「クリエイター」は半分から始まります。スタジオでの対話的な作業が、同じプランを共有する本番パイプラインの枠を食いつぶさないようにするためです。
管理者は/dashboard/workspaceの「メンバー」タブで、メンバーごとにパーセンテージでさらに絞り込めます。この個別設定はロールの割り当てを減らすことしかできず、ロールが認める以上に引き上げることはできません。
計算は一方向にしか重ならないので、結果は簡単に予測できます。
effective limit = base cap × plan multiplier × member share
Studioプランで、「クリエイター」ロールのメンバーが動画エンドポイントを呼ぶ場合:
6 × 4 × 0.5 = 12 video submissions per minute, per key
このメンバーを25%に絞ると6件になります。ここで起こらないことが2つあり、どちらも意図的な設計です。まず、絞られた割り当てが無料の読み取り専用エンドポイントを制限することはありません。ジョブの一覧表示やアカウント残高の確認はそのまま使えます。次に、生成がまったく許可されていないメンバーは、正体不明の429を次々に受け取るのではなく、クレジットが動くその時点で、明確な権限エラーによって拒否されます。
429の実際の中身
返ってくるのは、ステータスコード、秒単位のRetry-Afterヘッダー、そして対象のスコープと適用された上限を示すボディです。
{
"error": {
"message": "Rate limit reached for video (24/min per key). Retry in 37s.",
"type": "rate_limit_error",
"code": "rate_limit_exceeded"
}
}
役に立つのはヘッダーです。ウィンドウはスライドするので、Retry-Afterは固定のクールダウンではありません。現在のウィンドウで最も古いリクエストが期限切れになり、枠が1つ空くまでの秒数です。ちょうどその時間だけ待つのが正解で、1秒待って再試行するのは間違いです。
正しいバックオフ
ルールは4つです。優先度の高い順に並べます。
1. Retry-Afterがあれば、それに従う。実際のウィンドウから計算された値なので、自分で考えたどんな経験則よりも確かです。
2. なければ、ジッター付きの指数バックオフを使う。待ち時間を倍にするだけでは、すべてのクライアントが同じ瞬間に再試行するよう揃ってしまいます。フルジッター(0から現在の上限までのランダムな待ち時間)を使えば、タイミングが分散します。
3. 一時的でないエラーは再試行しない。402 insufficient_credits、403 plan_required、403 role_forbidden、そしてcontent_blockedによる拒否は、30秒後に送っても同じ答えが返ってきます。ユーザーに表示しましょう。503 model_unavailableは、そのエンジンが現在あなたのアカウントでは利用できないという意味です。再試行ループよりも、/modelsから別のエンジンを選ぶほうが良い対応です。
4. 壁に向かって再試行するのではなく、同時実行数に上限を設ける。実効上限と同じか、それより少し小さいサイズのセマフォを使えば、レート制限はエラー処理の問題から、本来あるべきスケジューリングの問題へと変わります。
全体をまとめると次のとおりです。そのまま貼り付けられる小ささです。
const sleep = ms => new Promise(r => setTimeout(r, ms))
async function submitVideo(body, { attempts = 5 } = {}) {
let delay = 1000
for (let attempt = 1; attempt <= attempts; attempt++) {
const res = await fetch('https://eroq.ai/v1/videos/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.EROQ_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})
if (res.ok) return res.json() // 202 with a job id
if (res.status !== 429) { // 402/403/503 are not transient
throw new Error(`${res.status} ${(await res.json()).error?.code}`)
}
const header = Number(res.headers.get('retry-after'))
const wait = Number.isFinite(header) && header > 0
? header * 1000
: Math.random() * delay // full jitter
await sleep(wait)
delay = Math.min(delay * 2, 30_000)
}
throw new Error('rate limited after all attempts')
}
ユーザーに直接関わる処理なら、5回の試行が妥当な上限です。バッチワーカーの場合は再試行ループそのものをやめ、送信レートを固定したキューにペース配分を任せましょう。制限に達する頻度はずっと少なくなり、達したときもキューが自然な待ち場所になります。
実際に最初に当たるのはどの制限か
実際には、ほとんどのチームが動画の上限に触れることはありません。1分に6件の送信は1時間で360件です。レート制限が文句を言うずっと前に、ウォレットが空になります。動画制作で本当に効いてくる制約はクレジットとレンダリングの実時間であり、だからこそ、この記事よりも予算の記事や/pricingのほうが重要なのです。
チャットは逆です。無料プランやHobbyプランの1分あたり60リクエストは、コンパニオンアプリやロールプレイのサービスが忙しい夜を迎えた途端、現実に届く数字です。ユーザーの発言1回ごとに1リクエストだからです。チャットを使って開発するなら、倍率を前提に計画し、画面や機能ごとにキーを分けて負荷を分散し、再試行の処理を設計する前にSSEストリーミングガイドを読んでください。応答の途中で切れたストリームは、そもそも始まらなかったリクエストとは別の扱いが必要です。
画像はその中間です。1分に20件は、対話的に使うには十分ですが、大量のカタログ制作には窮屈です。並列リクエストを一斉に投げるのではなく、自分で制御するキューを使うべき理由がここにもあります。
よくある質問
eroqのレート制限はキーごとですか、アカウントごとですか?
キーごとです。APIキーはそれぞれ独自の、スライドする1分間のウィンドウを持ちます。そのため、環境やパイプラインごとにキーを1つ発行しておけば、暴走したループがワークスペースの他の処理まで制限してしまうのを防げます。
プランをアップグレードするとレート制限は上がりますか?
はい。ドキュメントに記載の上限が基本値で、プランはすべてのキーでそれを倍にします。Creatorは2×、Studioは4×、Teamは6×、Agencyは8×です。キーの数もプランに応じて増えます。
動画エンドポイントから429が返ってきたらどうすればいいですか?
Retry-Afterヘッダーを読み、ちょうどその秒数だけ待ってから1回再試行してください。ヘッダーがない場合はフルジッター付きの指数バックオフを使い、同時実行数に上限を設けて、次のバッチが同じ壁にぶつからないようにしましょう。
この記事で使ったモデルで作ってみましょう。無料の50クレジットで始めるか、全エンジンと料金をご覧ください。