Skip to main content
Horizon requires an API key to use. You can get one by signing up at api.mathematicalcompany.com, or programmatically via the SDK.

Setup

Option A: Website (Manual)

1

Get your API key

Sign up at api.mathematicalcompany.com and copy your API key. Keys start with hz_live_.
2

Set the environment variable

Add this to your shell profile (~/.zshrc, ~/.bashrc, etc.):
export HORIZON_API_KEY="hz_live_abc123..."
Then reload your shell or run source ~/.zshrc.
3

Run your strategy

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.

Option B: Programmatic (Agentic)

Create an account and generate an SDK key entirely from the command line or through an AI agent. No browser required.
1

Install the SDK

pip install horizon-sdk
# or
uv pip install horizon-sdk
2

Run setup

Pass your password via the HORIZON_PASSWORD environment variable to avoid shell history exposure:
HORIZON_PASSWORD="your-password" python -c "
from horizon.auth import setup
result = setup('you@example.com', name='Your Name')
print(result)
"
This will:
  1. Try to log in (if you already have an account)
  2. Sign up if the account does not exist
  3. Generate a new SDK key
  4. Save the encrypted key to ~/.horizon/credentials.json
On success you will see:
{
  "status": "ok",
  "prefix": "hz_sdk_a1b2c3d",
  "credentials_path": "/home/you/.horizon/credentials.json",
  "message": "SDK key saved (encrypted) to ..."
}
If Supabase email confirmation is enabled, you will see "status": "confirmation_required". Check your email and confirm before running setup again.
3

Run your strategy

The engine auto-loads the key from ~/.horizon/credentials.json:
python my_strategy.py
Or set the env var explicitly:
export HORIZON_API_KEY="hz_sdk_..."

MCP / AI Agent Setup

AI agents using the MCP server or OpenClaw skill can call the auth tools directly:
ToolActionDescription
accountsetupCreate account and generate SDK key (full flow)
accountloginLogin to existing account and generate new key
accountkey_statusCheck if credentials are configured
The agent asks the user for their email, sets HORIZON_PASSWORD, and calls account(action="setup", params="{\"email\": \"...\"}"). The key is saved encrypted to disk and never returned in full in tool responses (only the prefix is shown).

Python API

from horizon.auth import (
    setup,           # Full flow: signup/login + key gen + save
    login,           # Login only
    signup,          # Signup only
    generate_sdk_key,  # Generate hz_sdk_ key
    hash_api_key,    # SHA-256 hash
    create_sdk_key,  # Insert key into Supabase
    save_credentials,  # Save encrypted to disk
    load_credentials,  # Load from disk
    resolve_password,  # Resolve from env var or argument
)

Security

  • Passwords: Always use the HORIZON_PASSWORD env var instead of passing passwords as CLI arguments. CLI arguments are visible in shell history and process listings.
  • Key storage: Credentials are encrypted at rest using a machine-derived key (hostname + username). The plaintext key is never written to disk.
  • Key exposure: Tool responses only include the key prefix, never the full key.
  • Rate limiting: Client-side rate limiting caps auth attempts to 5 per 60 seconds.

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:
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():
hz.run(
    name="my_strategy",
    api_key="hz_live_abc123...",
    markets=["test-market"],
    pipeline=[fair_value, quoter],
)
With Engine() directly:
from horizon import Engine, RiskConfig

engine = Engine(RiskConfig(), api_key="hz_live_abc123...")
The explicit parameter takes priority over the environment variable.

Resolution Order

PrioritySource
1api_key param in hz.run() / api_key param in Engine()
2HORIZON_API_KEY environment variable
3~/.horizon/credentials.json (saved by programmatic setup)

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 api.mathematicalcompany.com
If the key is invalid or expired:
RuntimeError: auth error: Invalid or expired API key. Check your key at
api.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:
rm ~/.horizon/license.json

Using with Docker

Pass the key as an environment variable:
ENV HORIZON_API_KEY="hz_live_abc123..."
Or at runtime:
docker run -e HORIZON_API_KEY="hz_live_..." my-strategy