OpenAI project API keys can expire: set max lifetime and rotate secrets
OpenAI now lets you set an expiration when you create a project API key, and admins can enforce a maximum key lifetime at the organization or project level in Platform settings. That is a real production control — newly issued keys cannot stay valid forever once the policy is on.
This post is the builder checklist: turn on max lifetime, create keys with an expiry, rotate before cutover, and keep secrets out of agent-readable paths. It is not an Agents API, Vercel Sandbox, or Astra walkthrough — for those, see OpenAI Agents API: what you still own when the harness is hosted and OpenAI Agents on Vercel: own the Queue and Sandbox hosting seam. The related secrets posture for install-time phishing is Fake Claude Code installers: keep keys out of agent-readable paths.
![]()
What shipped on September 10, 2026
Per the OpenAI API changelog (Sep 10, 2026):
- You can set expiration dates when creating project API keys.
- Administrators can enforce a maximum key lifetime at the organization or project level in Platform settings.
- Newly created keys must expire within the configured limit.
The same day also shipped the Agents API public beta and other model launches. Those are separate product surfaces. If your question is session orchestration or hosted sandboxes, stop here and read the Agents posts linked above. This article stays on key lifetime and rotation.
OpenAI's production best practices and API key safety guides match the changelog: set an expiration when you create a project key, run a regular rotation process, and let admins cap maximum lifetime so keys cannot remain valid indefinitely. Project limits cannot exceed the organization limit.

Set max lifetime in Platform settings first
Do the policy before you mint the next production key.
- Open Platform settings as an organization owner (or a role that can edit security policy).
- Set an organization-level maximum API key lifetime.
- Optionally tighten a per-project cap — it cannot exceed the org limit.
- Confirm that new keys must expire within that window.
What the policy does not do by itself:
- It does not magically expire every legacy key that was minted with no expiry.
- It does not rotate env vars in your deploy platform.
- It does not remove keys that coding agents already copied into chat logs,
.envfiles in the workspace, or prompt caches.
Treat the Platform setting as a gate on issuance. Inventory and rotation are still your job.
A practical starting window for most product teams is 30–90 days for runtime keys, shorter for CI break-glass keys. Pick a number your on-call can actually rotate without drama, then enforce it.
11 production screens. Login, database, payments — all wired.
The SaaS Dashboard Kit ships everything already connected. Nothing to set up. Live demo at saas.otf-kit.dev.
How to create a key that actually expires
Dashboard path
When you create a project API key in the dashboard, set an expiration date. OpenAI's safety guide is explicit: after that date, requests from the key are rejected. Before expiry, create a replacement, update applications, then revoke the old key once the replacement is verified.
Never put that secret in a browser, mobile client, or public repo. Route model calls through your backend and load the value from an environment variable or a secrets manager — the same guide's OPENAI_API_KEY pattern.
Admin API path (service accounts)
For automation, the verified Admin API field is expires_in_seconds on create project service account:
POST /v1/organization/projects/{project_id}/service_accounts
From the official create reference:
expires_in_seconds— optional number, minimum 1, maximum 31536000 (365 days).- If omitted or
null, the key does not expire unless the effective org/project policy requires an expiration. - When a maximum-lifetime policy is set, this value must be provided and must not exceed the policy limit.
- A non-null value cannot be used with
create_service_account_only: true. - The returned
api_keyobject may includeexpires_at(Unix seconds), ornullif it does not expire.
curl -X POST "https://api.openai.com/v1/organization/projects/$PROJECT_ID/service_accounts" \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "prod-runtime-2026-09",
"expires_in_seconds": 2592000
}'2592000 is 30 days. Store the returned api_key.value once — you will not see the full secret again — then put it in your secrets manager, not in the agent session transcript.
// Illustrative — Admin SDK surface names vary by version; field semantics match the REST docs.
const sa = await client.organization.projects.serviceAccounts.create(projectId, {
name: "prod-runtime-2026-09",
expires_in_seconds: 60 * 60 * 24 * 30, // 30 days; must be <= policy max
});
const secret = sa.api_key?.value;
const expiresAt = sa.api_key?.expires_at; // unix seconds, or null
// Write `secret` to your vault; never echo it into agent logs.If create fails after you turn the policy on, check two things before debugging the app: (1) you passed expires_in_seconds, and (2) the value is within both the schema max (365 days) and your org/project policy max.
Rotation that does not take production down
Expiration without rotation is just a scheduled outage. Use a two-key cutover:
- Mint the replacement with an expiry inside policy.
- Write the new value to the secrets store / deploy env as a second key (or swap under a single name after a canary).
- Roll app instances / workers so traffic uses the new secret.
- Verify live traffic (Usage dashboard + your own health checks).
- Revoke the old key from the API Keys page.
- Calendar the next rotation before
expires_at, not on the day it dies.
For CI, prefer short-lived keys or workload identity where you already have it, and keep the OpenAI secret out of fork PRs and world-readable logs. Monitor usage; unexpected spend is often the first signal a key leaked.

Keep keys out of agent-readable paths
Coding agents and chat UIs are a new leak surface. A key that lives in:
- a workspace
.envthe agent cancat - a prompt, PR description, or issue comment
- a screenshot of the dashboard
- a "debug" paste into an agent session
…is already shared beyond your rotation plan. Pair expiration with placement rules:
- Runtime secrets stay in the host secrets manager / platform env, injected at process start.
- Local dev uses a personal key with a short expiry, never the prod service-account key.
- Agents get scoped tools and no blanket read of production secret files.
- If a key might have been pasted into a chat, rotate it the same day — do not wait for
expires_at.
That is the same posture as the fake-installer post: assume anything an agent can read can leave the machine. Expiration bounds the blast radius; placement decides whether you need the bound.
What this does not replace
- IP allowlisting — still useful so even a valid key fails off trusted networks.
- Spend limits / usage alerts — expiration does not stop a leaked key from burning quota before it dies.
- Backend-only calls — mobile and browser clients should never hold the project key.
- Owned product secrets — your app's Stripe, DB, and auth secrets need the same lifetime discipline; OpenAI's Platform setting only covers OpenAI keys.
If you ship from an owned full-stack kit, wire OpenAI (and every other vendor key) through the same secrets layout the kit already expects for production deploys — one place to rotate, one place agents are told not to dump. The model or Agents harness can change next month; the secrets boundary should not.
A one-hour checklist you can run today
# 1) Confirm policy exists (Platform settings) — org max, optional project max
# 2) List project keys; note any with no expiry (legacy)
# 3) Create replacement service-account key with expires_in_seconds
# 4) Update vault / deploy env; roll workers
# 5) Revoke old key after verification
# 6) Schedule next rotation before expires_atTeam questions to answer out loud:
- Who is allowed to mint keys that can call production models?
- What is the org max lifetime, and does every project inherit or tighten it?
- Where do agents read env files today, and what is blocked?
- Who gets paged when Usage spikes or a key is seven days from expiry?
If you cannot answer those, the Sep 10 controls are unused surface area.
OpenAI gave you issuance policy and per-key expiry. Use both, rotate on a schedule, and keep the secret value somewhere an agent session cannot casually print. That is the whole change in production terms — not a reason to chase the parallel Agents/Astra launches unless those are the product you are actually shipping.
Sources
- OpenAI API changelog — Sep 10, 2026 (project API key expiration + max lifetime)
- Production best practices — API keys, expiration, rotation
- Best practices for API key safety
- Create project service account —
expires_in_seconds
Ship the product, not the setup.
- 11 production screens — auth, billing, team, analytics, settings
- Real database, payments, and login — all wired on day 1
- AI configs pre-tuned so your agent extends instead of regenerates