> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metrixllm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI Drop-in

> Route OpenAI requests through MetrixLLM with a one-line base URL change.

## Base URL

```text theme={null}
https://gateway.metrixllm.com/openai/v1
```

## Quick setup

<CodeGroup>
  ```python Python theme={null}
  from openai import OpenAI

  client = OpenAI(
      base_url="https://gateway.metrixllm.com/openai/v1",
      api_key="sk-metrix-YOUR_API_KEY"
  )

  response = client.chat.completions.create(
      model="gpt-4o",
      messages=[{"role": "user", "content": "Hello!"}]
  )
  print(response.choices[0].message.content)
  ```

  ```typescript Node.js theme={null}
  import OpenAI from "openai";

  const client = new OpenAI({
      baseURL: "https://gateway.metrixllm.com/openai/v1",
      apiKey: "sk-metrix-YOUR_API_KEY"
  });

  const response = await client.chat.completions.create({
      model: "gpt-4o",
      messages: [{ role: "user", content: "Hello!" }]
  });
  console.log(response.choices[0].message.content);
  ```

  ```bash cURL theme={null}
  curl -X POST https://gateway.metrixllm.com/openai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk-metrix-YOUR_API_KEY" \
    -d '{
      "model": "gpt-4o",
      "messages": [{"role": "user", "content": "Hello!"}]
    }'
  ```
</CodeGroup>

<Warning>
  Do **not** use your OpenAI API key. The gateway authenticates with MetrixLLM keys (`sk-metrix-*` prefix), then uses its own provider keys (or your BYOK keys) to call OpenAI.
</Warning>

## Request Headers

Every request supports these headers for authentication, tracing, and metadata:

| Header          | Type     | Required | Description                                        |
| --------------- | -------- | -------- | -------------------------------------------------- |
| `Authorization` | `string` | Yes\*    | `Bearer sk-metrix-{key}` — MetrixLLM API key       |
| `x-api-key`     | `string` | Yes\*    | `sk-metrix-{key}` — alternative to `Authorization` |
| `Content-Type`  | `string` | Yes      | Must be `application/json`                         |

**Session Tracing**

| Header                | Description                                                                  | Stored In                   |
| --------------------- | ---------------------------------------------------------------------------- | --------------------------- |
| `metrix-session-id`   | Unique session identifier — groups related requests into a traceable session | `workspace_logs.session_id` |
| `metrix-parent-id`    | Links a request to a parent span in the session trace                        | `workspace_logs.parent_id`  |
| `metrix-session-name` | Human-readable name for the span (for dashboard display)                     | `workspace_logs.span_name`  |

**Custom Properties**

Attach up to 10 custom metadata properties per request:

| Header Pattern          | Description                                                                        |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `metrix-property-{key}` | Custom metadata property. Used for rate limit targeting, analytics, and filtering. |

Example: `metrix-property-team: engineering`, `metrix-property-environment: production`

**IP Detection**

| Header            | Description                                          |
| ----------------- | ---------------------------------------------------- |
| `x-forwarded-for` | Client IP address (first IP in comma-separated list) |
| `x-real-ip`       | Fallback client IP header                            |
| `cf-ipcountry`    | Cloudflare country code of the connecting client     |

## Supported models

| Model        | ID             |
| ------------ | -------------- |
| GPT-4.1      | `gpt-4.1`      |
| GPT-4.1 Mini | `gpt-4.1-mini` |
| GPT-4o       | `gpt-4o`       |
| GPT-4o Mini  | `gpt-4o-mini`  |
| o3-mini      | `o3-mini`      |

## Routing mode

Control how the gateway authenticates with OpenAI using the `mode` parameter:

| Mode               | Behavior                                                               | Balance deduction                     |
| ------------------ | ---------------------------------------------------------------------- | ------------------------------------- |
| `"auto"` (default) | Uses your BYOK key if configured, otherwise falls back to platform key | BYOK: none. Native: yes               |
| `"byok"`           | Forces your own OpenAI API key (from workspace settings)               | None — your key, your cost            |
| `"native"`         | Forces MetrixLLM's platform key                                        | Yes — deducted from workspace credits |

<CodeGroup>
  ```python Python theme={null}
  # Use your own OpenAI key (BYOK) — never deducts workspace credits
  response = client.chat.completions.create(
      model="gpt-4o",
      mode="byok",
      messages=[{"role": "user", "content": "Hello!"}]
  )
  ```

  ```typescript Node.js theme={null}
  const response = await client.chat.completions.create({
      model: "gpt-4o",
      mode: "byok",
      messages: [{ role: "user", content: "Hello!" }]
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://gateway.metrixllm.com/openai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk-metrix-YOUR_API_KEY" \
    -d '{
      "model": "gpt-4o",
      "mode": "byok",
      "messages": [{"role": "user", "content": "Hello!"}]
    }'
  ```
</CodeGroup>

<Note>
  When `mode` is omitted (or `"auto"`), the gateway prefers your BYOK key if one is configured. If your workspace has insufficient credits and you have a BYOK key, the gateway automatically uses it instead of failing with a payment error.
</Note>

## Web search

### Web search mode (default)

Add `"web_search": true` to your request. The gateway performs a web search, generates optimized search queries, and injects the results into your system prompt.

<CodeGroup>
  ```python Python theme={null}
  response = client.chat.completions.create(
      model="gpt-4o",
      web_search=True,
      messages=[{"role": "user", "content": "What happened in the news today?"}]
  )
  ```

  ```typescript Node.js theme={null}
  const response = await client.chat.completions.create({
      model: "gpt-4o",
      web_search: true,
      messages: [{ role: "user", content: "What happened in the news today?" }]
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://gateway.metrixllm.com/openai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk-metrix-YOUR_API_KEY" \
    -d '{
      "model": "gpt-4o",
      "web_search": true,
      "messages": [{"role": "user", "content": "What happened in the news today?"}]
    }'
  ```
</CodeGroup>

**Parameters:**

| Parameter            | Type      | Default    | Description                                                                                      |
| -------------------- | --------- | ---------- | ------------------------------------------------------------------------------------------------ |
| `web_search`         | `boolean` | `false`    | Set to `true` to enable web search                                                               |
| `web_search_level`   | `string`  | `"medium"` | `"low"` (1 query, 3 results), `"medium"` (2 queries, 5 results), `"high"` (3 queries, 8 results) |
| `web_search_lang`    | `string`  | `"en"`     | Search language (ISO code)                                                                       |
| `web_search_country` | `string`  | `"us"`     | Search country (ISO code)                                                                        |

### Native mode

Set `"web_search": "native"` to use OpenAI's built-in web search. The gateway automatically converts your Chat Completions request into the **Responses API** format and adds the `{ "type": "web_search" }` tool.

<CodeGroup>
  ```python Python theme={null}
  response = client.chat.completions.create(
      model="gpt-4o",
      web_search="native",
      web_search_options={
          "search_context_size": "medium",
          "user_location": {
              "type": "approximate",
              "city": "San Francisco"
          }
      },
      messages=[{"role": "user", "content": "What's the weather in SF?"}]
  )
  ```

  ```typescript Node.js theme={null}
  const response = await client.chat.completions.create({
      model: "gpt-4o",
      web_search: "native",
      web_search_options: {
          search_context_size: "medium",
          user_location: { type: "approximate", city: "San Francisco" }
      },
      messages: [{ role: "user", content: "What's the weather in SF?" }]
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://gateway.metrixllm.com/openai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk-metrix-YOUR_API_KEY" \
    -d '{
      "model": "gpt-4o",
      "web_search": "native",
      "web_search_options": {
        "search_context_size": "medium",
        "user_location": {"type": "approximate", "city": "San Francisco"}
      },
      "messages": [{"role": "user", "content": "What'\''s the weather in SF?"}]
    }'
  ```
</CodeGroup>

**Native-specific parameters:**

| Parameter                                | Type     | Description                                                                     |
| ---------------------------------------- | -------- | ------------------------------------------------------------------------------- |
| `web_search_options.search_context_size` | `string` | `"low"`, `"medium"`, or `"high"` — controls how much search context is included |
| `web_search_options.user_location`       | `object` | Approximate user location for localized results                                 |

<Note>
  In native mode, the gateway converts your request from Chat Completions format to OpenAI's Responses API format. The response comes back in Responses API format — your code may need to handle both formats.
</Note>

## Streaming

```python theme={null}
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Tell me a story"}],
    stream=True
)
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
```

## Prompt management

Reference a stored prompt template by ID:

```python theme={null}
response = client.chat.completions.create(
    model="gpt-4o",
    prompt_id="your-prompt-uuid",
    inputs={"user_name": "Alice"},
    messages=[{"role": "user", "content": "Hello!"}]
)
```

## Custom properties

Attach metadata for analytics and rate limit targeting:

```python theme={null}
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
    extra_headers={
        "metrix-property-team": "backend",
        "metrix-property-env": "production",
        "metrix-session-id": "session_abc123"
    }
)
```

## Response headers

Every response includes these headers:

| Header                           | Description                                                             |
| -------------------------------- | ----------------------------------------------------------------------- |
| `Content-Type`                   | Always `application/json`                                               |
| `X-Metrix-Provider`              | Provider that served the request (e.g. `openai`, `anthropic`, `google`) |
| `X-Metrix-Model`                 | Exact model used for the request                                        |
| `X-Metrix-Cache-Status`          | `"HIT"` or `"miss"` (semantic cache)                                    |
| `X-Metrix-Retry-Count`           | Number of retry attempts (0 if none)                                    |
| `X-Metrix-Retry-Status`          | `"success"`, `"failed"`, or `"not_triggered"`                           |
| `X-Metrix-Fallback`              | `"true"` if a fallback provider was used (only when applicable)         |
| `X-RateLimit-Limit`              | Configured limit for the rate window                                    |
| `X-RateLimit-Remaining`          | Remaining quota in the current window                                   |
| `X-RateLimit-Requests-Remaining` | Remaining requests in current window                                    |
| `X-RateLimit-Tokens-Remaining`   | Remaining tokens in current window                                      |

On cache HIT responses, only `Content-Type` and `X-Metrix-Cache-Status: HIT` are returned.

On rate limited responses (`429 Too Many Requests`):

| Header                         | Description                                                           |
| ------------------------------ | --------------------------------------------------------------------- |
| `Retry-After`                  | Seconds to wait before retrying                                       |
| `X-RateLimit-{type}-Limit`     | Maximum limit (e.g. `X-RateLimit-rpm-Limit`, `X-RateLimit-tpm-Limit`) |
| `X-RateLimit-{type}-Remaining` | Remaining count in the current window                                 |
| `X-RateLimit-Reset`            | Seconds until the rate window resets                                  |
