# Gemini API key (production)

**Last updated:** 2026-04-10  

The **live** Ordio site (including the Firmennamen Generator API and any Gemini-backed PHP on `*.ordio.com`) must use a **dedicated production** Gemini Developer API key. **Do not** reuse personal dev keys from laptops for production billing isolation and blast-radius control.

Local development keys are documented in [`GEMINI_API_KEY_LOCAL.md`](GEMINI_API_KEY_LOCAL.md).

## What to set on the server

Same **priority idea** as ShiftOps Maps (`GOOGLE_MAPS_SHIFTOPS_API_KEY` → `google-maps-shiftops-api-key.php` — see [`SHIFTOPS_GOOGLE_MAPS_API_KEYS.md`](../systems/shiftops/SHIFTOPS_GOOGLE_MAPS_API_KEYS.md)):

| Source | Required | Notes |
|--------|----------|--------|
| `GEMINI_API_KEY` | Preferred | Production Gemini key; inject via PHP-FPM pool, Apache `SetEnv`, Docker, systemd — **never commit** |
| `v2/config/gemini-api-key.php` | Fallback | Gitignored; copy from `gemini-api-key.php.example`. Used in production **only if** env/constant are unset or still the placeholder |

**Env wins over the file.** If FPM has a wrong `GEMINI_API_KEY` (e.g. a Maps-only key), PHP will keep using it until you fix or remove that env line — the file fallback will not apply.

| Variable | Required | Notes |
|----------|----------|--------|
| `ORDIO_ENV` | Recommended | Set to `production` so CLI/cron and tooling match web behavior |
| `ORDIO_GEMINI_HTTP_REFERER` | Optional | Override URL sent as `Referer` on outbound Gemini REST calls (default `https://www.ordio.com/` in production). Use if your key’s HTTP-referrer allowlist uses a non-default pattern. |

The Firmennamen API sends a **non-empty `Referer`** to Gemini so API keys restricted to **HTTP referrers** still work from server-side PHP. Prefer **Application restrictions → None** or **IP addresses** for production keys; referrer restrictions are brittle for backends.

**Web requests** to `*.ordio.com` are treated as production even if `ORDIO_ENV` is unset (see `v2/config/gemini-environment.php`).

**CLI on the server** (cron, one-off SSH Python/PHP): set **`ORDIO_ENV=production`** and **`GEMINI_API_KEY`**. Python scripts do not see `HTTP_HOST`; without `ORDIO_ENV=production` they use the **local** key chain.

## Google Cloud setup

1. Use a **dedicated** API key for Gemini — **not** the ShiftOps / Maps browser key (`website-maps-shiftops`). Maps keys are restricted to Maps/Places; Gemini returns 403 *Generative Language API … are blocked* if you reuse them.
2. Enable **Generative Language API** for that project.
3. **API restrictions:** restrict the key to **Generative Language API** ([best practices](https://cloud.google.com/docs/authentication/api-keys-best-practices)).
4. **Application restrictions:** for server-side REST, use **none** or **IP** if egress is stable — not browser referrer restrictions.
5. Enable billing alerts / quotas as appropriate.

## Post-deploy smoke (SSH)

```bash
cd /path/to/landingpage   # adjust
export ORDIO_ENV=production
# GEMINI_API_KEY should already be in the environment from your stack
php v2/scripts/tools/test-gemini-key-resolution.php
php v2/scripts/tools/test-gemini-models.php
```

Expect **`ordio_gemini_is_production_context(): true`** when `ORDIO_ENV=production` is set, or when the script runs in a web context with `HTTP_HOST` ending in `ordio.com`. The diagnostic prints whether a key is present **without** revealing it.

If `test-gemini-models.php` returns 403 `API_KEY_HTTP_REFERRER_BLOCKED`, the key has browser-style restrictions — create a server-side key with **Application restrictions → None** (or IP), per [`GEMINI_API_KEY_LOCAL.md`](GEMINI_API_KEY_LOCAL.md) troubleshooting.

Do not paste keys into chat or logs.

## References

- [`GEMINI_API_KEY_LOCAL.md`](GEMINI_API_KEY_LOCAL.md) — local variables and migration
- [`GEMINI_OPTIMIZATION_GUIDE.md`](GEMINI_OPTIMIZATION_GUIDE.md) — models and costs
- [Gemini API keys (Google)](https://ai.google.dev/gemini-api/docs/api-key)
