OpenAI is the vendor behind the GPT models, Codex and the API playground. ZombieLicenseHunter connects directly to an OpenAI organization with an Admin API key — there is no OAuth redirect — to track token usage and cost per person, and which API keys are spending. Organization members are ingested as accounts, so zombie detection (dormant members, unused keys) works the same way it does for a directory integration.
Prerequisites
- Owner access to the OpenAI organization, so you can create an Admin API key.
- A decision to make with your eyes open: an OpenAI Admin API key cannot be scoped down or made read-only. The key ZombieLicenseHunter holds can also create and revoke API keys and change organization membership. There is no narrower key that can read usage or cost — every endpoint this integration reads requires an Admin API key — so, unlike some other integrations, there is no reduced-access mode to fall back on. If that is not acceptable, this integration is not for you.
Setup Instructions
Step 1: Create an Admin API Key
- In the OpenAI platform console, go to Organization settings → Admin keys.
- Create a new key.
- Copy the key — it is shown once.
A project key (sk-proj-…) is not an Admin API key. Project keys authenticate against the model APIs but are rejected by every organization endpoint, so one will not work here whatever permissions its owner holds.
Step 2: Connect in ZombieLicenseHunter
- Go to Integrations → Add Integration and select OpenAI as the Provider. Category is set to Usage automatically when OpenAI is selected; it is fixed for this provider and enforced on save.
- Paste the key into the Admin API key field.
- Click Save Integration. The key is encrypted and stored.
- An initial background sync begins immediately. Its first step checks the key against the organization members endpoint; a rejected key fails the sync with the error shown under Troubleshooting.
Step 3: Let the Backfill Complete
The first sync backfills 90 days of usage and cost history. The usage reports are fetched in 31-day windows because that is the vendor's maximum per request; the cost report covers the whole window in a single request series. Every sync after that refreshes a trailing window of the last few days rather than the full 90 days.
Usage is attributed to the member OpenAI names on the request. Playground traffic carries no API key, and OpenAI attributes it to the member who ran it, so it is recorded as that member's usage. Traffic through an API key with no member named is attributed to the key's owner — a person, or a service account.
Days are UTC. The current day is partial: OpenAI reports it as a bucket that is still filling, and its tokens and cost fill in on later syncs.
Step 4: Rotate the Key Later
To rotate the key, open the integration's edit page and enter a new Admin API key — the current one is never displayed, only replaced.
What Gets Synced
| Field | Description |
|---|---|
| Members | Organization members, ingested as accounts for zombie detection, with their organization role recorded as the licence type and their join date |
| Projects | Every project in the organization, archived projects included, so an archived project's keys and spend are still accounted for |
| Usage | Tokens per person or service account, per project, per model, per day, from the completions and embeddings reports |
| Cost | Dollars per person or service account, per cost line item, per day. Dollars are also recorded per project, but the usage page shows them as totals and per person, not per project |
| Keys | Every project API key, with its owner, its created, expiry and last-used dates, and whether its owner still has access to the project |
ChatGPT seats and ChatGPT Enterprise usage are not in this data at all. Only API traffic through the organization's keys and the playground appears. If you are looking for unused ChatGPT seats, this integration cannot see them.
No prompt or response content is read. The reports OpenAI exposes return aggregate counts and dollar amounts only.
Two other things worth knowing:
- Only the completions and embeddings reports are metered as tokens. OpenAI's other products — images, audio, moderations, web search, file search, code interpreter, vector stores — are not token-shaped. Their spend is still captured, because the cost report covers every line item, so you may see a person with dollars and no tokens. That is correct, not a bug.
- Cents are rounded per line item. OpenAI reports money as fractional dollars; ZombieLicenseHunter stores whole cents, rounded once per line item per person per day. A page total can therefore differ from the OpenAI dashboard's by a few cents.
Retention
Usage and cost rows are kept for 90 days and trimmed nightly after that. A member's last-active date is not trimmed with them — it persists on the account record beyond the 90-day window. If the nightly sweep would delete more than a fifth of a table, it refuses: nothing is deleted that night and the operator is alerted to trim the backlog in steps.
Troubleshooting
"openai: the key was rejected. The organization Admin API accepts only an Admin API key, created under Organization settings → Admin keys in the OpenAI platform console; a project key (sk-proj-…) cannot read organization members, usage or cost. Replace the key on the edit page"
This is shown as the integration's last sync error, followed by the HTTP status OpenAI returned. The key you pasted is a project key (sk-proj-…), or an Admin API key that has been revoked. To fix it, create an Admin API key under Organization settings → Admin keys, open the integration's edit page (there is no separate reconnect flow), and paste it into the Admin API key field. Saving starts a new sync that checks the key again.
A key shows "Owner access inactive"
The key still exists, but the person who owns it no longer has access to its project — usually because they were removed from the project but not from the organization. The key is still listed, because a credential that outlives its owner's access is exactly the finding this page exists to surface; delete it in the OpenAI console if it is no longer wanted.
A key owned by a service account
It has no person to offboard, so no departure will ever make it look stale. Judge it by its last-used date, which OpenAI reports directly on the key.
Someone has dollars but no tokens
They were billed for a product that is not metered as tokens — images, audio, web search, code interpreter and other tools — so there is spend to report and no token count to go with it. See "What Gets Synced" above.
"The provider could not break this window's cost down per person, so dollars are shown per project."
OpenAI does not accept a per-person cost breakdown for every organization and every date range. When it refuses one, ZombieLicenseHunter stores that window's dollars per project instead: they still count in the Cost total, but no one's per-person dollars include them, and the usage page shows this warning. Token figures are unaffected. Each sync asks for the per-person breakdown again, but only for the days it fetches — usually the last few — so days already stored per project stay that way until they age out of the 90-day window, even after the warning clears. If this happens on the first sync, the whole 90-day backfill is per project.
"No usage between …" versus "Not synced yet"
"No usage between …" means a sync has completed but found nothing for the selected dates — widen the date range. "Not synced yet" means no sync has completed — the initial sync may still be running. If the first sync failed, the page says "The sync failed, and there is no data to show" and shows the error instead; see the rejected-key entry above.
Vendor rate limits (429 errors)
The sync retries with backoff on rate-limited requests. A single 429 does not fail the sync; sustained rate limiting across retries will.