# Authentication

> What an API key reaches, which scope it needs, where to put it so the SDKs find it, and how to tell it is live.

Source: https://docs.levelfour.ai/authentication


Every request to the LevelFour API carries an API key. The prefix on the key says which environment it reaches, and the scope on it says what it may do there.

## API keys

Create keys in the LevelFour dashboard under **Settings > API Keys**, and pass one as a Bearer token.

### Key formats

| Prefix     | Environment | Use Case                              |
| ---------- | ----------- | ------------------------------------- |
| `l4_live_` | Production  | Live data, real optimizations         |
| `l4_test_` | Test        | Safe for development, no side effects |

## Key scopes

Each key carries a scope, set when you create it. The default is `read`. The API and SDKs take the values `read` and `read-write`, and the dashboard shows the same two as **Read-only** and **Read & write**.

| Scope (API value) | Dashboard label | Allowed                                                                                                                                                                                                                                                         |
| ----------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `read`            | Read-only       | All read endpoints: list and fetch costs, recommendations, savings, providers, commitments, and anomalies.                                                                                                                                                      |
| `read-write`      | Read & write    | Everything a `read` key can do, plus the endpoints that change state in LevelFour: accepting or rejecting a recommendation, adding rejection feedback, curating the resources a saving applies to, choosing an implementation method, and requesting execution. |

> **Error**
>
> A `read` key that calls a write endpoint receives `403 Forbidden` with the detail `API key scope insufficient`.

No key of either scope changes anything in your cloud account. Requesting execution starts the rollout in LevelFour and moves the recommendation's implementation to in progress. The step that reaches into your account is the savings grant. A `read-write` key can create one, but the grant only returns a link to scoped, time-limited access, and nothing changes until a person with access to your cloud account launches it.

Create read-only keys for monitoring, dashboards, and CI checks, and reserve `read-write` keys for automation that records decisions.

The [MCP server](/mcp) takes these keys too, alongside its own sign-in flow. Its writes carry a saving from the decision through to the rollout queue, plus virtual tags, cost alerts and anomaly status, and [Tools](/mcp/tools) lists every one. [Connecting a client](/mcp/authentication) compares the two credentials and says which scope each tool needs.

## Configuration

### Environment variable (recommended)

All SDKs auto-detect the `LEVELFOUR_API_KEY` environment variable:

```bash
export LEVELFOUR_API_KEY="l4_live_your_key_here"
```

**Python**

```python
from levelfour import LevelFour

client = LevelFour()
```

**TypeScript**

```typescript
import { LevelFourClient } from "levelfour";

const client = new LevelFourClient();
```

**Go**

```go
client, err := levelfour.NewClient("")
```

### Explicit API key

Pass the key directly to the constructor:

**Python**

```python
client = LevelFour(api_key="l4_live_your_key_here")
```

**TypeScript**

```typescript
const client = new LevelFourClient({ apiKey: "l4_live_your_key_here" });
```

**Go**

```go
client, err := levelfour.NewClient("l4_live_your_key_here")
```

## Verifying your key

Call the `whoami` endpoint:

**Python**

```python
me = client.auth.get_whoami()
print(me)
```

**TypeScript**

```typescript
const me = await client.auth.getWhoami();
console.log(me);
```

**Go**

```go
me, err := client.Auth.GetWhoami(context.Background())
```

> **Success**
>
> An answer from `whoami` is the proof the key is live. A data endpoint is weaker evidence, because it can fail for reasons that have nothing to do with the credential.

## Managing API keys

> **Note**
>
> Creating, listing, rotating, and revoking keys is available only to signed-in dashboard users, never to API keys, regardless of scope.

[API Keys](/account/api-keys) has the SDK method for each of those, its parameters, and the optional expiration date.

### Key rotation

Rotation creates a new secret for the same key ID. The old secret is immediately invalidated.

> **Warning**
>
> Store the new key immediately after rotation. It will not be shown again.

## Security best practices

> **Warning**
>
> Never commit an API key to version control. Keep it in an environment variable or a secrets manager, and rotate it the moment you suspect it has been compromised.

Reach for an `l4_test_` key in development and in CI/CD pipelines. Set an expiration date on any key you mint for a temporary integration.

## Next

* [API Keys](/account/api-keys) is every method for creating, listing, rotating and revoking a key
* [CLI authentication](/cli/authentication) is how `l4` resolves a credential, and the read-write key its write commands need
* [Connecting a client](/mcp/authentication) covers the sign-in flow an assistant can use instead of a key
* [Enterprise SSO (SAML)](/account/sso) is signing in to the dashboard with your own identity provider
