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

# Authentication

> One credential — your API key. Goes on every request as `x-api-key`.

`Minerva` is the single entry point. The only credential you need is your **API key**.

## Where to get your API key

<Steps>
  <Step title="Sign in">
    Log in at [app.minerva.io](https://app.minerva.io) (not available on the free tier).
  </Step>

  <Step title="Open Settings">
    Click your org name in the **bottom-left** → the three dots (`...`) → **Settings**.
  </Step>

  <Step title="Open the API tab">
    Open the **API** tab and copy your key. Treat it like a password.
  </Step>
</Steps>

## Use it

| Variable          | Used for                 |
| ----------------- | ------------------------ |
| `MINERVA_API_KEY` | every call the SDK makes |

```python theme={null}
from minerva import Minerva

mc = Minerva()                          # api_key from MINERVA_API_KEY env
mc = Minerva(api_key="mk_live_...")     # explicit
```

## Resolution order

<Steps>
  <Step title="Constructor argument">
    ```python theme={null}
    Minerva(api_key="mk_live_...")
    ```
  </Step>

  <Step title="Environment variable">
    `MINERVA_API_KEY`
  </Step>
</Steps>

If neither is set, the first call raises `MinervaAuthError("no API key (set MINERVA_API_KEY or pass api_key=).")`.

## Static egress IPs (production)

Outbound traffic Minerva sends to your endpoints — activation pushes,
webhooks, any Minerva-initiated callback — originates from a fixed set
of static IPs. If your security team needs to allowlist third-party
inbound traffic, allow these three addresses:

```
98.87.210.154
34.224.225.242
100.29.157.18
```

<Note>
  You do **not** need to allow these IPs for your SDK calls to reach
  `api.minerva.io` — outbound HTTPS from your side works without any
  allowlist. The list above only matters for traffic Minerva sends **to**
  your systems (activations / webhooks). If you don't receive
  Minerva-initiated traffic, you can skip this.
</Note>

## How it's sent

The SDK sends the API key as the `x-api-key` header on every request. There's
no token exchange, no session state, no rotation handled by the SDK — your
long-lived API key is the only credential. The server-side authorizer decides
what your key is entitled to.

```http theme={null}
POST /v2/enrich
x-api-key: mk_live_...
Content-Type: application/json

{ "records": [ ... ] }
```

## Rotating your key

Rotate your key in the Minerva web app. Once rotated:

* The old key continues working for the documented grace period (check your plan)
* Update `MINERVA_API_KEY` in your deployment / secret store
* Restart the process so a fresh `Minerva()` picks up the new value

## Errors you might see

| Error                                     | Meaning                                                                              |
| ----------------------------------------- | ------------------------------------------------------------------------------------ |
| `MinervaAuthError("no API key …")`        | Neither `api_key=` nor `MINERVA_API_KEY` set                                         |
| `MinervaAuthError` from a server response | 401 / 403 — your key is invalid, revoked, or not entitled to the endpoint you called |
| `MinervaRateLimitError(retry_after=…)`    | 429 — you're rate-limited; back off and retry                                        |

See [Error handling](/sdk/guides/error-handling) for the full hierarchy.
