Quickstart

From zero to a 200 response in under 60 seconds. curl required; nothing else.

Step 1 — Get an API key

Keys are issued on signup. A free-tier key gives you 100 calls/month across all 5 endpoints.

For this guide, substitute your key wherever you see axt_live_YOUR_KEY_HERE.

Step 2 — First call (curl)

Optimize a two-asset portfolio using Hierarchical Risk Parity. POST a 5-row return series (rows = time periods, columns = assets):

curl -X POST https://api.axistruth.com/v1/optimize-portfolio \
  -H "Authorization: Bearer axt_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "returns": [
      [0.01, -0.005],
      [0.02,  0.010],
      [-0.01, 0.005],
      [0.005, -0.002],
      [0.015, 0.008]
    ],
    "assetNames": ["SPY", "AGG"]
  }'

Expected response (200 OK):

{
  "weights": {
    "SPY": 0.38,
    "AGG": 0.62
  },
  "method": "hrp",
  "riskContributions": {
    "SPY": 0.5,
    "AGG": 0.5
  }
}
What HRP does: Hierarchical Risk Parity clusters assets by correlation structure and allocates weight so each cluster contributes equally to total portfolio risk. It does not require an expected-return estimate. Math per Lopez de Prado (2016).

Step 3 — Python (raw requests, no SDK)

import requests

API_KEY = "axt_live_YOUR_KEY_HERE"
BASE    = "https://api.axistruth.com"

payload = {
    "returns": [
        [0.01, -0.005],
        [0.02,  0.010],
        [-0.01, 0.005],
        [0.005, -0.002],
        [0.015, 0.008],
    ],
    "assetNames": ["SPY", "AGG"],
}

resp = requests.post(
    f"{BASE}/v1/optimize-portfolio",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json=payload,
    timeout=10,
)
resp.raise_for_status()
print(resp.json())

Step 4 — Node.js (native fetch)

const API_KEY = process.env.AXISTRUTH_API_KEY; // set in your env
const BASE    = "https://api.axistruth.com";

const payload = {
  returns: [
    [0.01, -0.005],
    [0.02,  0.010],
    [-0.01, 0.005],
    [0.005, -0.002],
    [0.015, 0.008],
  ],
  assetNames: ["SPY", "AGG"],
};

const res = await fetch(`${BASE}/v1/optimize-portfolio`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(payload),
});

if (!res.ok) {
  const err = await res.json();
  throw new Error(`AxisTruth error ${res.status}: ${err.message}`);
}

const data = await res.json();
console.log(data.weights);

Step 5 — Check your usage

Free tier is 100 calls/month. Check remaining quota at any time:

curl https://api.axistruth.com/v1/usage \
  -H "Authorization: Bearer axt_live_YOUR_KEY_HERE"

Returns:

{
  "used": 3,
  "limit": 100,
  "tier": "free",
  "resetAt": 1748822400
}

resetAt is a Unix timestamp (start of next calendar month UTC).

Common errors

Statuserror fieldCauseFix
401 unauthorized Missing or invalid API key Check the Authorization: Bearer <key> header
400 bad_request Schema validation failed Check message field for the failing field + constraint
429 rate_limit_exceeded Monthly quota exhausted Check resetAt in response; upgrade tier for higher limits
500 internal_server_error Unexpected server error Retry with exponential backoff; contact support@axistruth.com if persistent

What's next