# OpenAI

> See what you spend on OpenAI and who uses it. Connect the API bill, ChatGPT Enterprise, and the usage Codex and your own apps report.

Source: https://docs.levelfour.ai/connectors/openai


## What each plan can show

OpenAI publishes a bill for the API and per-person analytics for ChatGPT Enterprise and Edu. Codex reports its own usage to LevelFour on any plan, and so do your own apps through OpenTelemetry. Chat in ChatGPT is measured on Enterprise and Edu alone: on Business, Plus and Pro, OpenAI publishes nothing about it, and it does not run on your machine.

| Your plan                             | What you pay        | Connect                           | What you see                                                               |
| ------------------------------------- | ------------------- | --------------------------------- | -------------------------------------------------------------------------- |
| OpenAI API (platform.openai.com)      | Per token           | OpenAI Platform                   | Your bill by project, model, token type and API key                        |
| OpenAI API, called from your own apps | Per token           | App usage, beside OpenAI Platform | The same calls by app and model, valued at list price                      |
| ChatGPT Enterprise or Edu             | Seats, plus credits | ChatGPT Enterprise                | What each person used of ChatGPT, Codex and Work, in dollars or in credits |
| ChatGPT Business, Plus or Pro         | Seats or a flat fee | Codex usage                       | Who uses Codex and ChatGPT Work, with which model, and how much. Not chat  |

Connect any mix, in any order. Billing data holds no activity, so add **Codex usage** beside a bill to see sessions, prompts and tools next to what you pay.

A source can hold more than one account: a second OpenAI organization, a second ChatGPT workspace, or a settings block per team. Add another at any time from the same page. **Name** is optional free text, and LevelFour uses it only to tell accounts apart.

A ChatGPT workspace billed in credits shows credits. LevelFour does not turn credits into dollars, because the price of a credit is set in your agreement.

## History and what is left out

| Source             | History on connect                                               | First data                     | Not included                                                                                                                                                                           |
| ------------------ | ---------------------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OpenAI Platform    | 180 days, by day                                                 | About an hour                  | Tax                                                                                                                                                                                    |
| ChatGPT Enterprise | 90 days, by day                                                  | About an hour                  | Seat fees, prompts and responses                                                                                                                                                       |
| Codex usage        | From the day you add the settings. Codex reports nothing earlier | A few minutes after you verify | Your bill, chat in ChatGPT, Codex and Work tasks that run in OpenAI's cloud, developers who have not added the settings, and [what LevelFour never reads](#what-levelfour-never-reads) |
| App usage          | From the day you set the variables                               | A few minutes after you verify | Calls a trace sampler dropped, and calls your app made to another vendor                                                                                                               |

## Prerequisites

**OpenAI Platform**

* An organization on the OpenAI Platform.
* Organization owner access, to create the Admin key.

**ChatGPT Enterprise**

* A ChatGPT Enterprise or Edu workspace. ChatGPT Business has no analytics API.
* A workspace Owner or Admin, to create the workspace Admin key.

**Codex usage**

* Codex on each developer's machine: the CLI, the IDE extension or the ChatGPT app, on any plan.
* For a whole organization: an admin who manages your developers' machines, through MDM or a managed configuration file.

**App usage**

* An app that calls the OpenAI API through an official SDK.
* The OpenTelemetry SDK of the app's language, or an OpenTelemetry Collector the app already exports to.

## Connect

Open **Connect Providers** and select **OpenAI**. The first time an admin opens it, **Connect OpenAI** starts by itself; after that, click **Add account**. Pick each plan your company pays for and click **Continue**:

| Plan you pick                            | Steps it adds                                                             |
| ---------------------------------------- | ------------------------------------------------------------------------- |
| OpenAI API                               | OpenAI Platform: an Admin key, with Codex and Your apps as optional steps |
| ChatGPT Enterprise or Edu                | ChatGPT Enterprise: a workspace Admin key, with Codex as an optional step |
| ChatGPT Business, or ChatGPT Plus or Pro | Codex: a settings block                                                   |

Two plans with the same source share one step. You can skip a step or hand it to a colleague, and a review at the end lists what you connected and what is still open. Run it again at any time: it only adds accounts. Only admins connect, rotate and disconnect; a member or viewer sees each account and its status.

**OpenAI Platform**

### Create a read-only Admin key

Sign in to the OpenAI Platform as an organization owner. Open [**Admin keys**](https://platform.openai.com/settings/organization/admin-keys), click **Create new admin key**, and name it for LevelFour.

Under **Permissions**, give the key **Read** access and no **Write**, and set an expiration before you click **Create admin key**. If you change the permission later, OpenAI may not apply it. Copy the key (it starts with `sk-admin-`). OpenAI shows it once.

### Add it to LevelFour

In **Connect OpenAI**, pick **OpenAI API**. On the **OpenAI Platform** step, click **Add Admin API key**, paste the key and click **Connect account**.

LevelFour reads the costs report grouped by project, API key and line item, and the completions usage report for the tokens behind each charge. A charge that no API key made, such as a fine-tuning job, shows as **(no key)**. The account is the OpenAI organization the key belongs to, so a second key of an organization you already connected adds no account.

**ChatGPT Enterprise**

### Create a workspace Admin key

Sign in to the [ChatGPT Admin Console](https://chatgpt.com/admin) as a workspace Owner or Admin. Go to **Credentials > Admin keys** and create a key for LevelFour with **Read** on **Enterprise analytics API** and **Codex analytics API**. Copy it (it starts with `sk-admin-`). It is shown once.

Copy the **Workspace ID** from the workspace details page too.

### Add it to LevelFour

In **Connect OpenAI**, pick **ChatGPT Enterprise or Edu**. On the **ChatGPT Enterprise** step, click **Add workspace Admin key**, paste the key and the Workspace ID, and click **Connect account**.

LevelFour reads what each person used per day from the Enterprise analytics API, and the tokens of each Codex model from the Codex analytics API. A key with only one of the two permissions connects, and the account says which one it reads.

> **Warning**
>
> Seat fees are not in either API, so your ChatGPT Enterprise total is lower than your invoice. A workspace billed in credits shows credits and no dollars.

**Codex usage**

### Generate the settings

In **Connect OpenAI**, pick the plan that uses Codex. On the **Codex** step, click **Generate settings**. LevelFour shows a settings block that holds a new ingest key.

```toml title="~/.codex/config.toml"
[otel]
log_user_prompt = false
exporter = { otlp-http = { endpoint = "https://api.levelfour.ai/api/v1/otlp/v1/logs", protocol = "json", headers = { "Authorization" = "Bearer l4i_..." } } }
```

> **Warning**
>
> Copy the block before you leave the page. LevelFour keeps only a hash of the key and shows it this one time.

### Add it to Codex

* **One developer:** add the block at the end of `~/.codex/config.toml`, below every other setting. TOML puts each key under the table above it, so a block pasted at the top would capture the settings after it. Then quit Codex and the ChatGPT app and open them again: Codex reads the file when it starts. Codex reads it in the CLI, the IDE extension and the ChatGPT app.
* **Every developer in your organization:** encode the block in base64 with no line wrapping, and push it to Macs through MDM (preference domain `com.openai.codex`, key `config_toml_base64`). Without MDM, write the block to `/etc/codex/managed_config.toml` on macOS and Linux, or `~/.codex/managed_config.toml` on Windows. Codex applies it the next time it starts, so ask developers to quit and reopen Codex and the ChatGPT app.

A developer can still change a managed default during a session. LevelFour does not enforce collection.

> **Warning**
>
> A configuration file holds one `[otel]` table, so Codex on a machine reports to one key. If the file already has an `[otel]` table, replace it. A machine that also runs Codex against DeepSeek sends those sessions here too, and LevelFour leaves out each request for a model OpenAI does not serve.

The ChatGPT app runs Work tasks through the same Codex, so the block measures them too. They show as **ChatGPT Work**, apart from Codex. Chat in the app is not measured, and neither is a task that runs in OpenAI's cloud.

### Verify

Run one prompt in Codex, then click **Verify connection** in the step. If your rollout takes days, close the dialog: the block waits for its first event on the OpenAI page, and you verify it there later.

**App usage**

### Instrument the OpenAI SDK

Add the OpenTelemetry instrumentation of the OpenAI SDK to your app. In Python:

```bash
pip install opentelemetry-distro opentelemetry-exporter-otlp-proto-http opentelemetry-instrumentation-genai-openai
```

Run the app under `opentelemetry-instrument`, for example `opentelemetry-instrument python app.py`, and set `OTEL_SERVICE_NAME` to the name LevelFour should show for the app. Other languages have their own OpenAI instrumentation, and OpenLLMetry covers several.

`opentelemetry-instrumentation-genai-openai` traces chat completions, the Responses API and embeddings, and reports cached input, which LevelFour prices at the cache rate. It replaces `opentelemetry-instrumentation-openai-v2`, which traces no Responses API call and reports no cached input, so an app on it reads high.

> **Warning**
>
> A streamed chat completion carries token counts only when the app asks for them with `stream_options={"include_usage": True}`. Without it, the call reaches LevelFour with no tokens and is left out. A streamed Responses API call always carries them.

### Generate the variables

In **Connect OpenAI**, pick **OpenAI API**, then the optional **Your apps** step, and click **Generate settings**. LevelFour shows the environment variables with a new ingest key, once.

```bash title=".env"
OTEL_TRACES_EXPORTER=otlp
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://api.levelfour.ai/api/v1/otlp/v1/traces
OTEL_EXPORTER_OTLP_TRACES_HEADERS=Authorization=Bearer%20l4i_...
OTEL_TRACES_SAMPLER=always_on
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=false
```

### Set them where the app runs

Add the variables to the app's environment: its container, its deployment or its `.env` file. An app that already exports traces elsewhere keeps doing so through an OpenTelemetry Collector, with a second exporter for LevelFour. See [Sending through a Collector](#sending-through-an-opentelemetry-collector).

### Verify

Make one model call from the app, then click **Verify connection** in the step.

LevelFour reads only the spans of model calls. It reads a span of a chat, completion or embedding call and skips agent and workflow spans, which repeat the tokens of the calls under them. A call the sampler dropped never reaches LevelFour, which is why the variables keep every trace.

## What LevelFour keeps from Codex

Codex reports each thing a developer does as an event. LevelFour adds it to a daily total and stores the total, never one row per event.

| Kept            | As a daily total of                                                                                                      |
| --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Usage           | Requests, tokens by type and usage value, per person and model                                                           |
| Sessions        | Conversations started                                                                                                    |
| Prompts         | How many, and their length in characters                                                                                 |
| Tools           | Calls per tool, how many succeeded, and how long they took. A tool an MCP server serves counts as one row, **MCP tools** |
| Tool approvals  | Calls approved or denied, and what decided: configuration or a person                                                    |
| Failed requests | Model requests that did not go through, by status code where Codex sends one                                             |
| Speed           | Time to first token by model, and requests per reasoning effort                                                          |

LevelFour keeps usage, sessions, prompt counts and failed requests per person. Every other total covers all developers together and carries no name. Each person has one profile: the Codex version and terminal they last reported, and the first and last day they reported.

Codex reports no cost, so LevelFour values its tokens at OpenAI's API list price.

### What LevelFour never reads

Codex sends a tool's arguments and output with every tool result. LevelFour discards them unread. It never reads or stores:

* the text of a prompt or a response
* a tool's arguments or output
* a command
* file content

The settings block keeps `log_user_prompt` off, so Codex sends no prompt text.

### Who a request belongs to

A developer signed in to Codex with ChatGPT shows under their email, in the CLI and in the ChatGPT app. Codex signed in with an API key names no person, so LevelFour shows the account, or the machine when there is none. A developer who runs the CLI on an API key can name themselves by setting `OTEL_RESOURCE_ATTRIBUTES=levelfour.person=<their email>` in the shell Codex runs in. The ChatGPT app does not read your shell's variables, which it does not need: it is always signed in with ChatGPT.

### Sending through an OpenTelemetry Collector

You can put an OpenTelemetry Collector between Codex or your apps and LevelFour. Have it export OTLP over HTTP, as JSON or protobuf, to the route of each signal: `/api/v1/otlp/v1/logs` for Codex and `/api/v1/otlp/v1/traces` for apps. LevelFour refuses gRPC, a batch over 2 MB, and a batch that holds more than 1,024 model calls.

```yaml title="otel-collector.yaml"
exporters:
  otlphttp/levelfour:
    traces_endpoint: https://api.levelfour.ai/api/v1/otlp/v1/traces
    headers:
      Authorization: Bearer l4i_...
processors:
  filter/genai:
    error_mode: ignore
    traces:
      span:
        - >-
          attributes["gen_ai.usage.input_tokens"] == nil and attributes["gen_ai.usage.prompt_tokens"] == nil
          and attributes["gen_ai.usage.output_tokens"] == nil and attributes["gen_ai.usage.completion_tokens"] == nil
service:
  pipelines:
    traces/levelfour:
      receivers: [otlp]
      processors: [filter/genai]
      exporters: [otlphttp/levelfour]
```

The filter keeps only the spans that carry token counts, so the rest of your traces stay with your own backend. It reads the counts rather than `gen_ai.operation.name`, which older instrumentations leave out. An app that calls both OpenAI and DeepSeek sends through a Collector with one exporter per vendor, each with its own key: LevelFour leaves out a call that a key of the other vendor sent.

## What you see

OpenAI spend appears under [**Costs and Usage**](/cost-and-usage) and on its own **OpenAI** board under [**Boards**](/boards), which appears once you connect a source.

| Group by           | OpenAI Platform           | ChatGPT Enterprise                  | Codex and app usage          |
| ------------------ | ------------------------- | ----------------------------------- | ---------------------------- |
| Model              | The model                 | The product: ChatGPT, Codex or Work | The model                    |
| Project or tool    | Project                   | Client                              | Codex, ChatGPT Work or Apps  |
| Token type         | Input, Cache read, Output | Not reported                        | On the board's tokens card   |
| Key, person or app | API key, or **(no key)**  | Person                              | Person, or app for app usage |

### Billed and usage value

LevelFour keeps two figures apart, and a switch on the chart and the table chooses between them.

* **Billed** is what OpenAI charges you through the API, and what a ChatGPT workspace billed in dollars reports.
* **Usage value** is Codex and app usage priced at OpenAI's API list price. It estimates what that usage would cost per token. LevelFour never adds it to a billed total.

### The OpenAI board

The board sorts its cards into groups under headings. A card appears once it has data, and a heading appears once its group has a card. **Bill** reads OpenAI Platform and ChatGPT Enterprise. Every other group reads what Codex and your apps report, with the current day included.

| Group                 | Cards                                                                                                                                                                                                                                                  |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Bill                  | Spend summary, cost by model, by project or tool, by token type, and by key, person or app, the cost chart and table, active anomalies                                                                                                                 |
| Usage                 | Usage value, active people, requests and tokens; usage value and tokens per day; usage by person and by model; Codex versus apps; usage bands and concentration; cache efficiency; inactive people; people and apps, one row each, with a CSV download |
| Activity              | Sessions per day, prompts, new and returning people                                                                                                                                                                                                    |
| How Codex is used     | Tools used most, tool success rate, tool approvals                                                                                                                                                                                                     |
| Speed and reliability | Response time by model, rate limits and API errors, slowest tools, effort and fast mode                                                                                                                                                                |
| Fleet                 | Codex versions, terminals and IDEs                                                                                                                                                                                                                     |

Cards that compare people need two or more people who reported usage.

## Confirming it worked

Each account you connect moves to **Connected** on the OpenAI page. OpenAI Platform and ChatGPT Enterprise data appears in about an hour. Codex and app usage turn **Connected** after the first prompt or model call and **Verify connection**, and their figures appear on the board within minutes.

## Rotating or removing access

### Rotating a credential

Create a new key in OpenAI. On the OpenAI page under **Connect Providers**, click **Rotate credential** on the account, paste the new key, then revoke the old one where you created it.

You cannot rotate an ingest key. Disconnect the Codex or app usage source, keeping its data, generate the settings again, and replace the block or the variables wherever you put them.

### Removing access

Click **Disconnect** on the account under **Connect Providers**, then revoke the key: an Admin key on the OpenAI Platform's **Admin keys** page, a workspace Admin key under **Credentials > Admin keys** in the ChatGPT Admin Console. Disconnecting a usage source stops its ingest key working at once. Remove the block or the variables so Codex or your app stops sending.

## Troubleshooting

| Symptom                                                    | What to do                                                                                                                                                                                                                      |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| LevelFour rejects the OpenAI Platform key                  | OpenAI's organization reports refuse a project API key. Create an Admin key under **Admin keys**: it starts with `sk-admin-`                                                                                                    |
| Key creation fails or the Admin keys page is not visible   | You need organization owner access on the OpenAI Platform account                                                                                                                                                               |
| LevelFour rejects the ChatGPT Enterprise key               | Check the key has **Read** on **Enterprise analytics API** or **Codex analytics API**, and that you copied the Workspace ID of the workspace you created it in                                                                  |
| ChatGPT Enterprise shows credits and no dollars            | Expected for a workspace billed in credits                                                                                                                                                                                      |
| A charge shows **(no key)**                                | No API key made it, as with fine-tuning and some batch jobs                                                                                                                                                                     |
| **Verify connection** says no usage has arrived            | Check the block sits at the end of the `config.toml` Codex reads, quit and reopen Codex, then run one prompt. For an app, check the variables are in its environment, then make one model call. A chat in ChatGPT sends nothing |
| The account shows a warning that a model has no list price | A request used a model LevelFour cannot price yet. Its tokens count, at no cost, until LevelFour adds the price                                                                                                                 |
| Codex usage stopped after you set up Codex for DeepSeek    | The machine's `[otel]` table now names the DeepSeek key. A machine reports Codex to one key                                                                                                                                     |
| A Codex developer shows as an account id or a machine name | They use Codex with an API key. Have them set `levelfour.person`, as in [Who a request belongs to](#who-a-request-belongs-to)                                                                                                   |
| App calls are missing                                      | Check you started the app under the instrumentation, that no sampler drops traces, and that the app calls OpenAI itself. A streamed chat completion needs `stream_options={"include_usage": True}`                              |
| Azure OpenAI spend is missing                              | This page covers OpenAI itself. Azure bills Azure OpenAI, so [connect Azure](/connectors/azure) to see it                                                                                                                       |

## Next

* [Connect Providers](/connectors) lists every provider you can connect
* [Anthropic](/connectors/anthropic) and [DeepSeek](/connectors/deepseek) connect the same way
* [Virtual tags](/virtual-tags) group your OpenAI spend by team, product, or any other dimension, alongside your other providers
