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
| Status | error field | Cause | Fix |
|---|---|---|---|
| 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
- API Reference — complete schemas for all 8 endpoints
- Playbook — 5 worked recipes (rebalancing, Kelly sizing, factor attribution, stress scenarios, bot integration)
- Rate limit headers —
X-RateLimit-*fields for programmatic quota tracking