> For the complete documentation index, see [llms.txt](https://docs.otari.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.otari.ai/otari/for-operators/openai.md).

# OpenAI provider guide

Route requests to OpenAI models (GPT-4o, GPT-4.1, the o-series, and others) through Otari. See any-llm's [supported providers](https://docs.mozilla.ai/any-llm/providers/) for the current provider list and [Models](/otari/for-operators/models.md) for Otari's model-name format.

## What you'll set up

An OpenAI provider entry in your `config.yml` that reads your key from `OPENAI_API_KEY` (or the key stored on the dashboard's Providers page), then a first request that Otari routes to OpenAI.

## Prerequisites

* Otari running locally (see the [Quickstart](/otari/start-here/quickstart.md))
* An OpenAI account and an API key from <https://platform.openai.com/api-keys>

## Configure

Add OpenAI under `providers:` in your `config.yml`:

```yaml
providers:
  openai:
    api_key: "sk-..."                        # your OpenAI API key
    # api_base: "https://api.openai.com/v1"  # optional; override for a proxy or compatible endpoint
```

To keep your provider key out of the file with environment interpolation:

```yaml
providers:
  openai:
    api_key: ${OPENAI_API_KEY}
```

...then export it before starting Otari:

```bash
export OPENAI_API_KEY=sk-...
```

> `OPENAI_API_KEY` alone is not enough, and neither is a bare `openai:` entry: Otari reads the variable only where an entry names it, as the `api_key: ${OPENAI_API_KEY}` line above does. The dashboard's Providers page and an organization's own key work too. Otari logs a warning at startup when the variable is set and no entry reads it.

### Optional settings

`client_args` are passed through to the underlying `any-llm` provider client, for options such as custom headers or timeouts:

```yaml
providers:
  openai:
    api_key: ${OPENAI_API_KEY}
    client_args:
      timeout: 60
      custom_headers:
        OpenAI-Organization: "org-..."
```

## Choose a model

Models are addressed as `openai:<model>`:

```
openai:gpt-4o
openai:gpt-4o-mini
openai:o4-mini
```

Everything after the colon is passed straight to OpenAI, so any model your key can access works.

## Verify

If you have not already started Otari and created a client key, follow the [Quickstart](/otari/start-here/quickstart.md) through step 3 first.

Then make a request with the Otari Python SDK (`pip install otari`; any OpenAI-compatible client also works), using an `openai:<model>` selector:

```python
from otari import OtariClient

client = OtariClient(api_base="http://localhost:8000", api_key="tk-...")
resp = client.completion(
    model="openai:gpt-4o-mini",
    messages=[{"role": "user", "content": "Say hello in five words."}],
)
print(resp.choices[0].message.content)
```

Expected (sample) output:

```
Hello, nice to meet you!
```

## Troubleshooting

| Symptom                                                                                                                                                             | Likely cause                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| HTTP 424 `The provider rejected the gateway's credentials` (code `provider_credential_rejected`)                                                                    | The `api_key` Otari sent to OpenAI is invalid or lacks access. Check the `api_key` (or `OPENAI_API_KEY`) configured on the gateway.                                                                                                                                                                                                                                                                             |
| HTTP 404 (OpenAI's own "model not found" text)                                                                                                                      | The name after `openai:` is not a model your key can access, or the model name is misspelled. A rejection of your request carries OpenAI's own message, so the detail says which model it could not find. `The requested model was not found on the provider` appears instead when OpenAI sent no message at all.                                                                                               |
| HTTP 502 `The upstream provider account is out of credit or over its billing limit.`                                                                                | The provider rejected the call because the account Otari billed has no credit left or has hit its billing limit (for example OpenAI's "billing hard limit reached", or Anthropic's "credit balance is too low", which arrives as a 400). Top up the provider account, or point the model at a provider that has credit. The usage log keeps the status the provider actually returned, so these stay countable. |
| HTTP 502 `The provider failed the request with HTTP 5xx`, `The provider closed the connection before answering`, or `The gateway could not connect to the provider` | OpenAI failed on its side or the connection to it broke. These are retryable. `LLM provider error` is the same answer for a failure Otari could not place.                                                                                                                                                                                                                                                      |
| HTTP 402 `No pricing configured for model ...`                                                                                                                      | Otari could not resolve pricing for that model and `require_pricing` rejected the request. Add a `pricing:` entry, enable `default_pricing: true` for bundled fallback pricing, or use a model that already has pricing coverage.                                                                                                                                                                               |
| HTTP 401 `Invalid master key` on `/api/v1/keys`                                                                                                                     | You passed a client (`tk-...`) key, or the wrong master key, instead of the configured master key.                                                                                                                                                                                                                                                                                                              |

## Pricing (optional)

To track cost for a model, add a `pricing:` entry in `config.yml`:

```yaml
pricing:
  openai:gpt-4o-mini:
    input_price_per_million: 0.15
    output_price_per_million: 0.60
```

See [Configuration](/otari/for-operators/configuration.md) for all options.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.otari.ai/otari/for-operators/openai.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
