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

# Authentication

> How to authenticate with the Ornn Data API using a Bearer API key, and which endpoints require one.

The Ornn Data API authenticates requests with an **API key** passed as a Bearer token, and not every endpoint requires one.

## The Authorization header

Send your key in the `Authorization` header on every request to a protected endpoint:

```
Authorization: Bearer YOUR_API_KEY
```

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.ornnai.com/api/gpu/H100%20SXM" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  resp = requests.get(
      "https://api.ornnai.com/api/gpu/H100 SXM",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
  )
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://api.ornnai.com/api/gpu/H100 SXM", {
    headers: { Authorization: "Bearer YOUR_API_KEY" },
  });
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init("https://api.ornnai.com/api/gpu/" . rawurlencode("H100 SXM"));
  curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_KEY"],
  ]);
  $data = json_decode(curl_exec($ch), true);
  ```

  ```go Go theme={null}
  package main

  import (
  	"net/http"
  	"net/url"
  )

  func main() {
  	endpoint := "https://api.ornnai.com/api/gpu/" + url.PathEscape("H100 SXM")
  	req, _ := http.NewRequest("GET", endpoint, nil)
  	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
  	resp, _ := http.DefaultClient.Do(req)
  	defer resp.Body.Close()
  }
  ```

  ```java Java theme={null}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  HttpClient client = HttpClient.newHttpClient();
  HttpRequest request = HttpRequest.newBuilder(
          URI.create("https://api.ornnai.com/api/gpu/H100%20SXM"))
      .header("Authorization", "Bearer YOUR_API_KEY")
      .build();
  HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
  ```

  ```ruby Ruby theme={null}
  require "net/http"

  uri = URI("https://api.ornnai.com/api/gpu/H100%20SXM")
  req = Net::HTTP::Get.new(uri)
  req["Authorization"] = "Bearer YOUR_API_KEY"
  res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
  ```
</CodeGroup>

## Getting a key

API keys are created in the dashboard, not through the API. Sign in to [data.ornn.com](https://data.ornn.com), go to **Settings → API Keys**, and create one. See [Manage API keys](/docs/manage-api-keys) for details.

<Warning>
  Your full key (`sk_live_...`) is shown **only once**, at creation. Store it somewhere safe. If you lose it, revoke it and create a new one. You cannot retrieve it later.
</Warning>

## Which endpoints need a key?

Ornn Data's access tiers mirror what you can already see for free on [index.ornn.com](https://index.ornn.com). A specific set of GPU and token indices is public with a limited history window; an API key unlocks the full history, every other index, and the premium datasets.

**Public GPU indices** (current price + **trailing 3 months** of history, no key): `H100 SXM`, `H200`, `B200`, `A100 SXM4`, `RTX 5090`.

**Public token indices — OTPI** (current value + **trailing 1 month** of history, no key): `anthropic`, `openai`, `google`, `deepseek`.

| Access                                    | Endpoints                                                                                                                                                                                                                                                                                                                                                 |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Public — GPU, 3-month window**          | `/api/gpu/{gpuName}` (current price), `/api/daily-index`, `/api/daily-index/all`, `/api/day-index` (deprecated), `/api/daily-index/{gpuName}/previous`, `/api/gpu/{gpuName}/index-history`, `/api/h100-history` — **free-5 GPUs only**                                                                                                                    |
| **Public — token (OTPI), 1-month window** | `/api/otpi` — **free-4 labs only**                                                                                                                                                                                                                                                                                                                        |
| **Public — no data windowing**            | `/health`; catalogs `/api/gpu-types`, `/api/gpu-types-free`, `/api/token-types`, `/api/token-types-free`, `/api/memory-types`, `/api/llm-coding/products`                                                                                                                                                                                                 |
| **API key required (gated completely)**   | Every other index: `RTX PRO 6000 WS` and other GPUs, OTPI labs outside the free-4, memory spot prices & history, the Workload Cost Index (`/api/workload`), LLM coding analytics (`/api/llm-coding/index` and `/api/llm-coding/history`), all analytics (volatility, utilization), point-in-time & ranged GPU history, and neo-cloud datacenter site data |

<Note>
  On the windowed endpoints, an anonymous request returns the free window and includes `"access": "public-3mo"` (GPU) or `"public-1mo"` (OTPI). Send your API key to reach the full history — the response then returns `"access": "full"`. A `startDate` earlier than the free window, a non-free GPU, or a non-free OTPI lab is only served with a key (otherwise `401`). The Workload Cost Index and LLM coding analytics do not have a free window: `/api/workload`, `/api/llm-coding/index`, and `/api/llm-coding/history` require a key on every request.
</Note>

<Tip>
  To discover the free-vs-paid split at runtime — for example to render a pricing table — pair the full catalog with its `-free` companion: `/api/gpu-types` with [`/api/gpu-types-free`](/docs/api-reference/reference/list-free-tier-gpu-models), and [`/api/token-types`](/docs/api-reference/token-prices/list-tracked-otpi-labs) with [`/api/token-types-free`](/docs/api-reference/token-prices/list-free-tier-otpi-labs). The `-free` routes return the same list regardless of caller tier.
</Tip>

<Note>
  Public index and catalog routes that use the public limiter are limited to 60 requests/minute per IP. Because the limiter runs before optional authentication, sending a valid API key does not switch those requests to a separate per-key limit. See [Rate limits](/docs/rate-limits).
</Note>

## Authentication errors

If the key is missing, malformed, or invalid, you get a `401`:

```json theme={null}
{
  "error": "Unauthorized",
  "message": "API key required. Use Authorization: Bearer YOUR_API_KEY"
}
```

```json theme={null}
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

A revoked key returns `{"error": "Unauthorized", "message": "API key is inactive"}`. See [Errors & status codes](/docs/errors) for the full list.
