---
title: "Authentication"
description: "Set up your Horizon API key to use the SDK."
icon: "key"
---

Horizon requires an API key to use. Get yours at [horizon.mathematicalcompany.com](https://horizon.mathematicalcompany.com).

## Setup

<Steps>
  <Step title="Get your API key">
    Sign up at [horizon.mathematicalcompany.com](https://horizon.mathematicalcompany.com) and copy your API key.
    Keys start with `hz_live_`.
  </Step>
  <Step title="Set the environment variable">
    Add this to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.):

    ```bash
    export HORIZON_API_KEY="hz_live_abc123..."
    ```

    Then reload your shell or run `source ~/.zshrc`.
  </Step>
  <Step title="Run your strategy">
    ```bash
    python my_strategy.py
    ```

    That's it. The SDK validates your key once at startup and caches the result locally. There is **zero latency impact** on trading.
  </Step>
</Steps>

## How It Works

1. **Startup only**  - validation happens once when `Engine` is created (inside `hz.run()`). After that, no network calls are made during trading.
2. **Local cache**  - a successful validation is cached at `~/.horizon/license.json` for 72 hours. The raw key is never stored, only a SHA-256 hash.
3. **Offline grace period**  - if the network is unavailable but a valid cache exists for your key, the SDK allows startup. No internet dependency during cached periods.
4. **Compiled in Rust**  - the validation logic is in the compiled binary, not in bypassable Python code.

## Configuration

There are two ways to provide your API key:

### Environment Variable (Recommended)

```bash
export HORIZON_API_KEY="hz_live_abc123..."
```

This is the recommended approach. Set it once in your shell profile and forget about it.

### Explicit Parameter

You can pass the key directly in code  - useful for notebooks, testing, or when you don't want to set environment variables.

**With `hz.run()`:**

```python
hz.run(
    name="my_strategy",
    api_key="hz_live_abc123...",
    markets=["test-market"],
    pipeline=[fair_value, quoter],
)
```

**With `Engine()` directly:**

```python
from horizon import Engine, RiskConfig

engine = Engine(RiskConfig(), api_key="hz_live_abc123...")
```

The explicit parameter takes priority over the environment variable.

### Resolution Order

| Priority | Source |
|----------|--------|
| 1 | `api_key` param in `hz.run()` / `api_key` param in `Engine()` |
| 2 | `HORIZON_API_KEY` environment variable |

## Error Messages

If the key is missing:

```
RuntimeError: auth error: No Horizon API key provided. Set HORIZON_API_KEY
or pass api_key to hz.run(). Get your key at horizon.mathematicalcompany.com
```

If the key is invalid or expired:

```
RuntimeError: auth error: Invalid or expired API key. Check your key at
horizon.mathematicalcompany.com
```

If there's a network error and no cached validation:

```
RuntimeError: auth error: Could not validate API key (network error) and no
cached validation found. Check your internet connection.
```

## Cache Location

The license cache is stored at:

```
~/.horizon/license.json
```

To force re-validation (e.g., after upgrading your plan), delete this file:

```bash
rm ~/.horizon/license.json
```

## Using with Docker

Pass the key as an environment variable:

```dockerfile
ENV HORIZON_API_KEY="hz_live_abc123..."
```

Or at runtime:

```bash
docker run -e HORIZON_API_KEY="hz_live_..." my-strategy
```
