GEMINI LABEN
API — Event-driven WebhooksでBatch APIや長時間処理の完了を通知受信。ポーリングが不要になりますSEARCH — File Searchがgemini-embedding-2に対応し、画像もネイティブに埋め込み・検索できますSECURITY — 6/19以降、未制限APIキーからのリクエストが遮断されました。キー制限の点検をMODEL — Gemini 3.5 Flashが一般提供。gemini-flash-latestの本体になりましたAGENT — Managed AgentsがGemini APIで公開プレビュー。隔離サンドボックスで自律エージェントを実行できますDEPRECATED — 画像プレビュー2モデルが6/25で停止。preview依存の処理は確認しておきましょうAPI — Event-driven WebhooksでBatch APIや長時間処理の完了を通知受信。ポーリングが不要になりますSEARCH — File Searchがgemini-embedding-2に対応し、画像もネイティブに埋め込み・検索できますSECURITY — 6/19以降、未制限APIキーからのリクエストが遮断されました。キー制限の点検をMODEL — Gemini 3.5 Flashが一般提供。gemini-flash-latestの本体になりましたAGENT — Managed AgentsがGemini APIで公開プレビュー。隔離サンドボックスで自律エージェントを実行できますDEPRECATED — 画像プレビュー2モデルが6/25で停止。preview依存の処理は確認しておきましょう
記事一覧/API / SDK
API / SDK/2026-06-28中級

Gemini API の『未制限キー遮断』で自動運用が止まる前に、キーの制限を点検する

2026年6月19日以降、制限のない Gemini API キーからのリクエストが遮断されるようになりました。自分のキーが対象かを確かめ、本番を止めずに制限を足す手順を整理します。

Gemini API149APIキーセキュリティ3自動運用

ある朝、定期実行しているスクリプトのログに 403 PERMISSION_DENIED がずらりと並んでいて、心臓が少し冷えました。コードは一行も変えていません。変わったのは Gemini API 側の運用ポリシーでした。2026年6月19日以降、利用制限をかけていない「未制限キー」からのリクエストが遮断されるようになっています。不正利用や意図しない課金を防ぐための変更ですが、放置気味に動かしていた自動処理ほど、ある日いきなり静かに止まる類の更新です。

厄介なのは、エラーの見た目が「キーに制限をかけすぎて弾かれる」ケースとよく似ている点です。原因の切り分けを誤ると、せっかく足した制限をまた外してしまい、振り出しに戻ります。ここでは、自分のキーが対象かを確かめ、稼働中の処理を止めないまま制限を足していく流れを、個人開発で自動処理を日々回している、私自身の点検手順に沿って整理します。

「未制限キー」とは具体的に何を指すのか

Google Cloud / AI Studio で発行する API キーには、大きく二種類の制限を設定できます。ひとつは、そのキーで叩ける API を絞る「API 制限」。もうひとつは、リクエスト元を絞る「アプリケーション制限」(HTTP リファラー・IP アドレス・Android/iOS アプリなど)です。どちらも設定していないキーが、今回遮断対象になった「未制限キー」です。

つまり「Generative Language API だけ有効にしてある」状態でも、アプリケーション制限が空なら未制限扱いになります。私は当初ここを勘違いしていて、「API は絞ってあるから大丈夫」と思い込んでいました。実際には両方を見られていると考えたほうが安全です。

制限の種類絞る対象未制限のままだと
API 制限このキーで呼べる API(例: Generative Language API のみ)漏れた際にあらゆる API を叩かれうる
アプリケーション制限リクエスト元(リファラー / IP / アプリ)誰がどこから使ってもキーが通る

まず自分のキーが対象かを確かめる

管理画面を開く前に、稼働中のスクリプトから直接叩いて、いま通っているのか弾かれているのかを確かめます。個人開発の小さなスクリプトでは、私は切り分け用に、生成ではなく models の一覧取得のような軽い呼び出しを使っています。本処理と同じキーで叩くのが要点です。

# 稼働中の自動処理と同じ環境変数のキーで叩く
curl -s -o /dev/null -w "%{http_code}\n" \
  "https://generativelanguage.googleapis.com/v1beta/models?key=${GEMINI_API_KEY}"

200 が返れば現時点では通っています。403 なら本文を確認します。レスポンスの error.message に「API key not valid」ではなく、リクエスト元やキーの制限に関する文言が出ているかで、未制限遮断なのか別の制限エラーなのかを見分けます。

curl -s "https://generativelanguage.googleapis.com/v1beta/models?key=${GEMINI_API_KEY}" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); e=d.get('error',{}); print(e.get('status'), '|', e.get('message'))"

ここで「リファラー制限により拒否された」系のメッセージが出る場合は、今回の未制限遮断ではなく、制限のかけ方そのものの問題です。その切り分けは「Gemini API キーに HTTP リファラー制限をかけたら本番サイトから 403 エラーになる原因と対処」で扱っているので、症状が一致したらそちらを確認してください。

本番を止めずに制限を足す——「既存キーを直接いじらない」

ここがいちばん事故りやすいところです。稼働中のキーの制限欄を直接編集して保存すると、設定が反映された瞬間から、想定外の呼び出し元がすべて弾かれます。自分の頭の中にあるリクエスト元と、実際にそのキーを使っている場所がずれていると、その差分がそのまま障害になります。私は一度これで、想定し忘れていたバッチ用サーバーを巻き込みかけました。

そこで、既存キーには触れず、制限済みの新しいキーを並行して用意し、検証してから差し替える形を取ります。

  1. 制限を設定した新規キーを発行する(API 制限=Generative Language API のみ、アプリケーション制限=実際の呼び出し元に合わせる)
  2. 新キーを本番とは別の環境変数(例: GEMINI_API_KEY_NEXT)に置き、検証スクリプトで 200 を確認する
  3. 想定する全ての呼び出し元(ローカル・CI・本番サーバー)から新キーで通ることを確かめる
  4. 問題なければ本番の環境変数を新キーへ差し替える
  5. 旧キーは即削除せず、数日ログを見て参照が消えてから無効化する

差し替え自体の安全な進め方は「Gemini API キーをダウンタイムゼロでローテーションする実装パターン」と同じ考え方です。新旧を一定期間併存させ、ログで参照ゼロを確認してから落とす、という順序を守るとほぼ事故りません。

自動運用で「静かに止まる」を防ぐ常設のカナリア

今回いちばん怖かったのは、エラーそのものより「気づくのが遅れたこと」です。定期実行は成功も失敗も同じように静かなので、403 が出ても次の実行までログを見なければ分かりません。そこで、本処理の冒頭に軽い疎通確認を一つ挟み、特定のエラーだけ検知して自分に通知するようにしました。

// 本処理の前に1回だけ叩く疎通確認。403 PERMISSION_DENIED のときだけ通知する
async function assertKeyUsable(apiKey) {
  const url =
    "https://generativelanguage.googleapis.com/v1beta/models?key=" + apiKey;
  const res = await fetch(url);
  if (res.ok) return;
 
  const body = await res.json().catch(() => ({}));
  const status = body?.error?.status ?? String(res.status);
  const message = body?.error?.message ?? "unknown error";
 
  // 制限・キー無効など、設定起因の遮断だけを区別して扱う
  if (res.status === 403) {
    await notifyMe(`Gemini API key blocked: ${status} / ${message}`);
    throw new Error(`KEY_BLOCKED: ${message}`);
  }
  // 5xx など一時的な失敗は握りつぶさず、通常のリトライへ委ねる
  throw new Error(`API check failed: ${res.status} ${message}`);
}

notifyMe の中身は、私の場合は自分宛ての簡単な通知で十分でした。大事なのは「設定が原因の遮断(403)」と「サーバー側の一時障害(5xx)」を同じ扱いにしないことです。前者は人が制限を直さないと永遠に直りませんが、後者は待てば戻ります。一緒くたにリトライへ流すと、直らない遮断を延々と叩き続けて、別の課金やレート制限を呼び込みます。

次の一手

まずは手元の全キーを一覧で出し、「アプリケーション制限が空のもの」を洗い出してください。AI Studio や Google Cloud のキー一覧で、制限列が空のキーが今回の対象です。一つでも未制限のキーが自動処理に使われているなら、上の「新キーで検証してから差し替える」手順で、稼働を止めずに制限を足すところから始めるのが安全です。放置運用ほど、止まる前の点検が効いてきます。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-04-28
Gemini API キーをダウンタイムゼロでローテーションする実装パターン
Gemini API キーの定期ローテーションと漏えい時の即時切替を、本番サービスを止めずに行うための設計パターンを実装コード付きで解説します。デュアルキー構成、Cloudflare Workers Secrets、自動フェイルオーバー、漏えい60分対応まで網羅。
API / SDK2026-06-27
Project Spend Caps とアプリ側ソフト上限で、無人パイプラインの費用事故を二重に止める
Gemini API の Project Spend Caps(月額ドル上限)と、ハード上限の手前で止まるアプリ側ソフトサーキットブレーカーを二段構えにする設計。Python と sqlite による日次コスト台帳の実装コードつき。
API / SDK2026-06-27
Gemini の構造化出力でJSONのフィールド順がブレる — propertyOrdering で固定する実装メモ
responseSchema で型を縛っているのに、出力JSONのキーの並びが呼び出しごとに変わる。スナップショットテストが理由なく赤くなる原因はこれでした。propertyOrdering でフィールド順を固定し、few-shot の順序も揃え、差分ノイズを消すまでをコード付きでまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →