---
title: "API keys"
subtitle: "Create, scope, limit, and revoke the keys that authenticate gateway requests."
---

Every gateway request carries a Respan API key. The key decides which project the request is logged in, whether it counts as test or production traffic, what it's allowed to do, and which limits apply. Use one key per app and environment so you can limit or revoke each one on its own.

<Tabs>
<Tab title="cURL">
```bash
curl https://gateway.respan.ai/v1/chat/completions \
  -H "Authorization: Bearer $RESPAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```
</Tab>
<Tab title="Python">
```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://gateway.respan.ai/v1",
    api_key=os.environ["RESPAN_API_KEY"],
)

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Hello!"}],
)
```
</Tab>
<Tab title="TypeScript">
```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://gateway.respan.ai/v1",
  apiKey: process.env.RESPAN_API_KEY,
});

const response = await client.chat.completions.create({
  model: "gpt-5.5",
  messages: [{ role: "user", content: "Hello!" }],
});
```
</Tab>
</Tabs>

| Setting | Description |
| --- | --- |
| [Environment](#environment) | **Production** or **Test**. Keeps data apart in Logs and dashboards. |
| [Permissions](#permissions) | **Read**, **Write**, **Gateway**, **Admin**. |
| [Expiry](#expiry) | The date after which the key is refused. |
| [IP ranges](#ip-ranges) | `allowed_ip_ranges`: the addresses the key may be used from. |
| [Limits](#limits) | Monthly spend limit, usage cap, requests and tokens per minute. |

## Create a key

<Steps>
<Step title="Open API keys">

Go to **Gateway** › **API keys** and click **New key**. The same page is at **Settings** › **API Keys**.

</Step>
<Step title="Choose the environment and permissions">

Name the key, pick **Production** or **Test**, and choose its permissions. Then click **Create**.

<img src={"/docs/images/gateway-quickstart/create-api-key-light.webp"} width="420" className="block dark:hidden" alt="The Create new key dialog with Name, Environment (Production or Test), and Permissions: Read, Write, Gateway, and Admin" />
<img src={"/docs/images/gateway-quickstart/create-api-key-dark.webp"} width="420" className="hidden dark:block" alt="The Create new key dialog with Name, Environment (Production or Test), and Permissions: Read, Write, Gateway, and Admin" />

</Step>
<Step title="Copy the key">

Click **Copy**, then **Done**. You won't see the key again, so save it now:

```bash
export RESPAN_API_KEY="your-respan-api-key"
```

</Step>
</Steps>

<Warning>
Treat a key like a password. Keep it out of source control and client-side code, and call the gateway from your server. If a key leaks, [revoke it](#revoke-a-key) and create a new one.
</Warning>

## Environment

**Production** and **Test** keep data apart. Logs and dashboards have an environment switch that shows **Production**, **Test**, or **All environments**. Requests sent with a test key, and Playground runs, show under **Test**. With environment-scoped provider keys, a request that sends the `x-respan-beta: env-scoped-integrations-2026-03-28` header uses only the provider keys saved for its key's environment. See [Bring your own key](/docs/ai-gateway/spend/credits-vs-byok#byok).

## Permissions

| Permission | Allows |
| --- | --- |
| **Read** | Viewing project data. |
| **Write** | Creating, editing, and deleting project data. Includes **Read**. |
| **Gateway** | Sending requests through the gateway. |
| **Admin** | Managing API keys and limits. |

New keys get **Read**, **Write**, and **Gateway**. A key that only calls models needs **Gateway** alone, so give it nothing more. A key created by another key can't get more permissions than the key that created it.

## Expiry

Set an expiry date when you create or edit a key. After it, requests with the key are refused. For short-lived keys, such as one per contractor or demo, create them with the API (see [Create keys with the API](#create-keys-with-the-api)).

## IP ranges

A key's `allowed_ip_ranges` lists the IP addresses or CIDR ranges it may be used from, such as `203.0.113.0/24`. Requests from any other address are refused before they reach a provider. An empty list means any address. A key created by a key that has IP ranges can only narrow them.
{/* REVIEW: confirm where customers set allowed_ip_ranges (dashboard field or documented API), any max number of ranges, and the status and code a refused address gets. */}

## Limits

Each key can have a monthly `spending_limit`, a lifetime `max_usage`, a requests-per-minute `rate_limit`, and a tokens-per-minute `tpm_rate_limit`. Set them on the key's page below **Permissions**. Over the spend limit, requests get `402` `plan_permission_denied`. See [Budgets and limits](/docs/ai-gateway/spend/budgets-and-limits).

## Find, tag, and edit keys

The list shows each key's prefix, tags, last use, expiry, spend, limits, status, and environment. Hover a row and click **Add tag** to tag it. Click a key to open it, change what you need, click **Save**, and confirm.

<img src={"/docs/images/admin/api-keys-list-light.png"} className="block dark:hidden" alt="The API keys list with columns for Key, Tags, Last used, Expires, Usage, Spend limit, Status (Active, Temporary, Revoked), and Env (Prod or Test)" />
<img src={"/docs/images/admin/api-keys-list-dark.png"} className="hidden dark:block" alt="The API keys list with columns for Key, Tags, Last used, Expires, Usage, Spend limit, Status (Active, Temporary, Revoked), and Env (Prod or Test)" />

## Revoke a key

Open the key and click **Revoke key**, or open the row's **⋯** menu and click **Revoke key**. Click **Confirm**. Requests that use the key are refused right away.

To rotate a key without downtime, create the new key first, deploy it, and check that new requests show up in **Logs**. Then revoke the old key.

## Create keys with the API

Use the [Temporary API keys](/docs/apis/api-keys/create-temporary-api-key) endpoint to create short-lived keys. The key you call it with needs the **Admin** permission. Each new key gets the calling key's permissions unless you set `permissions_override`, and it can't get more than the calling key has.

```bash
curl https://api.respan.ai/api/temporary-keys/ \
  -H "Authorization: Bearer $RESPAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Contractor demo",
    "is_test": true,
    "expiry_date": "2026-12-31T00:00:00Z",
    "spending_limit": 25,
    "limit_policies": [{"metric": "cost", "period": "day", "max_value": 5}]
  }'
```

The response's `api_key` is the only time you see the key. Manage its caps later with the [Limit policies API](/docs/apis/limit-policies/create-limit-policy).

## Send the key

| Where | How |
| --- | --- |
| HTTP requests | `Authorization: Bearer <key>` |
| Anthropic SDK on `/v1/messages` | Pass the Respan key as the SDK's API key and point its base URL at the gateway |
| Gemini SDK on `/v1beta/...` | Pass the Respan key as the SDK's API key |
| OpenAI Realtime WebSocket | `Authorization` header, or the `openai-insecure-api-key.<key>` subprotocol |
| Gemini Live WebSocket | `x-goog-api-key` header or `?key=` |

{/* REVIEW: confirm gateway.respan.ai accepts the Anthropic SDK's x-api-key header on /v1/messages and the Gemini SDK's x-goog-api-key on /v1beta. */}

When you're signed in to the platform, the Playground calls the gateway with your session instead of an API key, as the project's Playground key, so those requests show under **Test**.

## Next steps

- [Bring your own key](/docs/ai-gateway/spend/credits-vs-byok#byok)
- [Budgets and limits](/docs/ai-gateway/spend/budgets-and-limits)
- [Security overview](/docs/ai-gateway/security/overview)
