GEMINI LABJP
PRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration windowPRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration window
Articles/API / SDK
API / SDK/2026-06-28Intermediate

Audit Your Gemini API Key Restrictions Before the Unrestricted-Key Block Stops Your Automation

Since June 19, 2026, requests from unrestricted Gemini API keys are blocked. Here is how to check whether your key is affected and add restrictions without taking your production automation down.

Gemini API190API Key2Security4Automation13

One morning my scheduled script's log was full of 403 PERMISSION_DENIED, and my stomach dropped a little. I hadn't changed a single line of code. What changed was the Gemini API policy: since June 19, 2026, requests from keys with no usage restrictions are blocked. It's meant to curb abuse and unexpected billing, but it's exactly the kind of change that quietly stops the automation you've been running on autopilot.

The tricky part is that the error looks a lot like the opposite problem—a key that's restricted too tightly and gets rejected. If you misread which one you're hit by, you'll strip out the restriction you just added and end up back where you started. Below is the order I actually follow as an indie developer running these jobs daily: confirm whether your key is affected, then add restrictions without interrupting anything that's already running.

What "unrestricted" actually means

A key issued from Google Cloud / AI Studio supports two broad kinds of restriction. One is the API restriction, which limits which APIs the key may call. The other is the application restriction, which limits where requests may come from (HTTP referrers, IP addresses, Android/iOS apps). A key with neither set is the "unrestricted" key that is now blocked.

So a key that has "only the Generative Language API enabled" is still unrestricted if its application restriction is empty. I got this wrong at first, assuming "the API is locked down, so I'm fine." In practice it's safer to assume both dimensions are being checked.

Restriction typeWhat it limitsIf left unset
API restrictionWhich APIs the key can call (e.g. Generative Language API only)A leaked key can hit any API
Application restrictionRequest origin (referrer / IP / app)Anyone, anywhere, can use the key

First, confirm whether your key is affected

Before opening any console, call the API directly with the key your running script uses, and see whether it passes or gets blocked right now. For my small indie-developer scripts, I use a light call for triage—listing models rather than generating—and the key point is to use the same key as the real job.

# Use the exact same key your automation reads from its env
curl -s -o /dev/null -w "%{http_code}\n" \
  "https://generativelanguage.googleapis.com/v1beta/models?key=${GEMINI_API_KEY}"

A 200 means it passes for now. On 403, read the body. Whether error.message says "API key not valid" versus something about the request origin or key restrictions tells you whether this is the unrestricted-key block or a different restriction error.

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'))"

If the message is about a referrer restriction rejecting the request, this isn't the unrestricted-key block—it's a problem with how the restriction itself is configured. That case is covered in "The 403 Error When You Add HTTP Referrer Restrictions to a Gemini API Key," so check there if the symptom matches.

Add restrictions without downtime—never edit the live key in place

This is where it's easiest to cause your own outage. The moment you edit a running key's restriction fields and save, every request origin you didn't account for gets rejected. Any gap between the origins in your head and the places actually using that key becomes an incident. I once nearly took down a batch server I'd simply forgotten about doing exactly this.

So leave the existing key alone, stand up a new restricted key in parallel, validate it, and swap.

  1. Issue a new key with restrictions set (API restriction = Generative Language API only; application restriction = your real origins)
  2. Put the new key in a separate env var (e.g. GEMINI_API_KEY_NEXT) and confirm 200 with the check script
  3. Verify it passes from every origin you expect—local, CI, production server
  4. Once clean, point the production env var at the new key
  5. Don't delete the old key immediately; watch the logs for a few days and disable it only after references drop to zero

The safe mechanics of the swap follow the same idea as "A Zero-Downtime Rotation Pattern for Gemini API Keys": keep old and new side by side for a while, confirm zero references in the logs, then retire the old one. Keep that order and you almost never get burned.

A standing canary so automation never fails silently

What scared me most wasn't the error itself—it was how late I noticed. Scheduled jobs are equally quiet on success and failure, so a 403 can sit unseen until the next run. So I added one light reachability check at the top of the job that detects this specific error and notifies me.

// A one-shot reachability check before the real work; notify only on 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";
 
  // Single out config-driven blocks (bad/blocked key) from transient failures
  if (res.status === 403) {
    await notifyMe(`Gemini API key blocked: ${status} / ${message}`);
    throw new Error(`KEY_BLOCKED: ${message}`);
  }
  // Let 5xx and other transient errors fall through to your normal retry path
  throw new Error(`API check failed: ${res.status} ${message}`);
}

In my case notifyMe is just a simple note to myself, which was enough. What matters is not treating a "config-driven block (403)" the same as a "transient server error (5xx)." The former never fixes itself until a human edits the restriction; the latter recovers if you wait. Lump them into the same retry loop and you'll hammer an unfixable block forever, inviting more billing or rate limits.

Your next step

Start by listing every key you hold and flagging the ones with an empty application restriction. In the AI Studio or Google Cloud key list, a blank restriction column marks this round's targets. If even one unrestricted key feeds an automated job, the safest place to begin is the "validate a new key, then swap" flow above—adding restrictions without stopping anything that's running. The more hands-off the setup, the more a check before it breaks pays off.

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API / SDK2026-04-28
Rotating Gemini API Keys with Zero Downtime in Production
A practical playbook for rotating Gemini API keys without dropping production traffic. Covers dual-key fallback, Cloudflare Workers Secrets, automatic failover clients, and the first sixty minutes of a leak response.
API / SDK2026-06-30
Fire-and-Forget on a Cron That Never Loses a Result: Reclaiming Gemini Background Executions with a Submission Ledger
A design for running the Interactions API's background execution safely from a cron-driven runner. We reserve a row in a ledger by idempotency key before submitting, then reclaim only outstanding handles on the next tick — shown with working code.
API / SDK2026-06-27
Stopping Runaway Costs Twice: Project Spend Caps Plus an App-Side Soft Limit
Pairing Gemini API Project Spend Caps (a monthly USD ceiling) with an app-side soft circuit breaker that trips before the hard cap. Includes a working Python and sqlite daily cost ledger.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →