Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mathematicalcompany.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

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_sdk_.
2

Set the environment variable

Add this to your shell profile (~/.zshrc, ~/.bashrc, etc.):
export HORIZON_API_KEY="hz_sdk_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_sdk_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_sdk_abc123...",
    markets=["test-market"],
    pipeline=[fair_value, quoter],
)
With Engine() directly:
from horizon import Engine, RiskConfig

engine = Engine(RiskConfig(), api_key="hz_sdk_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_sdk_abc123..."
Or at runtime:
docker run -e HORIZON_API_KEY="hz_sdk_..." my-strategy