Documentation

Volatility regime API for crypto. REST + WebSocket. Base URL: https://api.amaneki.com/v1

Quickstart

curl https://api.amaneki.com/v1/regime/btcusdt

No key needed for the free tier (60 req/min per IP). For higher limits, persistent key, and webhook alerts, get a paid key — pricing.

Rate limits in HA: the service runs on two Fly machines behind round-robin routing, each with its own in-memory counter. Within a single minute the effective limit you'll observe is the per-tier cap as a floor, not a hard ceiling (burst-dependent; a short burst that hits both machines can clear ~1.3–1.5× the advertised rpm before throttling engages). Plan budgets against the advertised value; treat the over-allowance as coincidental headroom, not a contract.

New to the API? Walk through the 10-minute quickstart (curl → Python SDK → Discord webhook) before scanning this reference.

Prefer a live sandbox? Interactive API reference — Scalar, rendered from the same /openapi.json you'd feed to openapi-generator, Stainless, or Speakeasy to auto-build a typed client.

Clients

Three examples of the same call — pick your language:

curl -H "Authorization: Bearer ak_..." \
  https://api.amaneki.com/v1/regime/btcusdt?timeframe=15m
# Python (pip install amaneki)
from amaneki import Client
c = Client(api_key="ak_...")
print(c.get_regime("btcusdt", timeframe="15m"))
// JavaScript / TypeScript — plain fetch
const r = await fetch(
  "https://api.amaneki.com/v1/regime/btcusdt?timeframe=15m",
  { headers: { Authorization: "Bearer ak_..." } }
);
console.log(await r.json());
// Go
req, _ := http.NewRequest("GET",
  "https://api.amaneki.com/v1/regime/btcusdt?timeframe=15m", nil)
req.Header.Set("Authorization", "Bearer ak_...")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)

Authentication

Send your key as a Bearer token:

curl -H "Authorization: Bearer ak_..." https://api.amaneki.com/v1/regime/btcusdt

Or as a header:

curl -H "X-API-Key: ak_..." https://api.amaneki.com/v1/regime/btcusdt

Use cases

Five ways customers have used the API. The endpoint reference below is organised by category; this section is the inverse — organised by the problem you're solving.

Endpoints — Regime

GET /v1/regime/{symbol}

Current regime for one (symbol, timeframe).

ParamDefaultNotes
timeframe1mOne of 1m, 5m, 15m, 1h, 4h, 1d
{
  "symbol": "btcusdt",
  "timeframe": "1m",
  "regime": "normal",
  "z_vol": -0.83,
  "realized_vol": 0.23,
  "baseline_vol": 0.29,
  "close": 74915.42,
  "last_update_ms": 1776324240000,
  "seconds_in_state": 18420,
  "last_transition": null
}

GET /v1/regime/{symbol}/custom

Re-run the FSM against the in-memory feature window with caller-supplied thresholds. Stateless; doesn't affect the broadcast stream or the preset detector.

curl "https://api.amaneki.com/v1/regime/btcusdt/custom?high_enter=2.5&low_enter=-2.0&enter_k=3"
ParamDefaultNotes
timeframe1m
high_enterz-score to enter high
low_enterz-score to enter low (negative)
enter_kconsecutive bars required

GET /v1/regime/{symbol}/history

Past regime transitions. Without from_ms/to_ms, returns the in-memory ring buffer (~last 1024 transitions since process start). With either, queries Postgres for the full archive.

curl "https://api.amaneki.com/v1/regime/btcusdt/history?timeframe=15m&limit=200"
ParamDefault
timeframe1m
limit100 (max 1024)
from_ms
to_ms

GET /v1/regime/{symbol}/matrix

3×3 transition probability matrix (rows: from-regime, cols: to-regime) over the archive window. Diagonal reports persistence.

curl "https://api.amaneki.com/v1/regime/btcusdt/matrix?timeframe=15m&lookback_days=30"

GET /v1/regime/{symbol}/durations

Empirical duration distribution per regime (seconds spent before exiting). Returns median/mean/p25/p75/p95 per regime label.

curl "https://api.amaneki.com/v1/regime/btcusdt/durations?timeframe=15m"

GET /v1/regime/{symbol}/state_at

Regime label at an arbitrary millisecond timestamp. Resolves by scanning the transition archive.

curl "https://api.amaneki.com/v1/regime/btcusdt/state_at?timeframe=15m&ts_ms=1776324240000"

GET /v1/regime/{symbol}/explain

Why the FSM is in its current state: which threshold crossed, which counter tripped, how many bars since the last flip. Useful for debugging "why didn't this transition fire?"

curl "https://api.amaneki.com/v1/regime/btcusdt/explain?timeframe=15m"

GET /v1/regime/{symbol}/conditional-returns

Empirical next-bar log-return distribution conditioned on the current regime. Mean, std, quantiles (p05/p25/p75/p95), samples, and baseline (unconditional distribution) so callers can quantify how much the regime label shifts the distribution.

curl "https://api.amaneki.com/v1/regime/btcusdt/conditional-returns?timeframe=15m"

Use this for attribution ("given the regime just flipped to HIGH, what's the next-bar return distribution historically?"), not as a point forecast. No model of direction — the mean is usually small and not a trading signal.

GET /v1/regime/{symbol}/forecast — deprecated

Alias of /conditional-returns kept for existing clients. Response body is identical; the response carries Deprecation: true, Sunset: Sat, 30 Jan 2027 00:00:00 GMT, and Link: …/conditional-returns; rel="successor-version". Migrate before 2027-01-30.

curl -i "https://api.amaneki.com/v1/regime/btcusdt/forecast?timeframe=15m"

GET /v1/regime/{symbol}/top-down

Multi-timeframe regime alignment. Returns whether the regime label agrees across the chain from_tf → … → to_tf, which TFs aligned, and the full per-timeframe dictionary. Use for Dow-theory / MTF-confluence entries without hitting /regime/{sym} N times.

curl "https://api.amaneki.com/v1/regime/btcusdt/top-down?match=high&from_tf=1d&to_tf=15m"
ParamDefaultNotes
matchhighwhich regime must align: low | normal | high
from_tf1dslowest TF in the chain
to_tf15mfastest TF in the chain

GET /v1/regime/{symbol}/stories

Human-readable narrative of recent regime transitions for the symbol. Designed for chat bots, LLM tool-calls, and daily summary emails — one sentence per transition, most recent first.

curl "https://api.amaneki.com/v1/regime/btcusdt/stories?days=7&timeframe=15m"
ParamDefaultNotes
days71-90
timeframe15m
limit501-200

GET /v1/regime/{symbol}/matrix

Bar-level transition probability matrix over lookback_days, reconstructed from the postgres event archive (falls back to in-memory ring when the archive is empty for that series). Diagonal = stay-in-state probability, off-diagonal = per-bar switch probability.

curl "https://api.amaneki.com/v1/regime/btcusdt/matrix?timeframe=15m&lookback_days=90"

GET /v1/regime/{symbol}/durations

Distribution of regime run-lengths in bars. Summary stats (mean, median, p90, max, samples) per state over lookback_days, postgres-backed.

curl "https://api.amaneki.com/v1/regime/btcusdt/durations?timeframe=15m&lookback_days=90"

GET /v1/regime/{symbol}/impact

Realized return distribution following transitions into a target regime, at fixed horizons (1h, 4h, 24h). For each past transition, price at t+h is compared to price at t. Returns sample_size plus horizons with median, mean, std, p05/p25/p75/p95.

Gets more useful over time: every new transition adds a sample. On a fresh symbol or a rare target regime, sample_size can be 0. Always check the field before trusting the stats.

curl "https://api.amaneki.com/v1/regime/btcusdt/impact?to=high&timeframe=15m&lookback_days=60"
ParamDefaultNotes
tohighlow | normal | high
timeframe1m
lookback_days301-365

GET /v1/regime/lead-lag

Do transitions in leader precede matching transitions in follower? For each leader event into the target regime, scans forward up to max_lag_minutes for a follower event of the same kind. Returns hit_rate plus median/mean/p25/p75 of the matched lags in minutes.

Data-accumulation-based. A 7-day lookback on a quiet pair will match almost nothing. Prefer lookback_days ≥ 60 and read matched before trusting hit_rate.

curl "https://api.amaneki.com/v1/regime/lead-lag?leader=btcusdt&follower=ethusdt&to=high&timeframe=15m&lookback_days=60&max_lag_minutes=60"
ParamDefaultNotes
leaderrequired
followerrequired
tohighlow | normal | high
timeframe1m
lookback_days601-365
max_lag_minutes601-1440

Endpoints — Consensus & Market Context

GET /v1/consensus/{symbol}

Majority vote across Binance, Coinbase and Bybit. Each venue computes its own regime from its own klines; consensus reports which venues agreed. Useful for catching single-venue wicks.

curl "https://api.amaneki.com/v1/consensus/btcusdt?timeframe=15m"

GET /v1/consensus/{symbol}/multi-tf

Pro Plus only. Cross-venue consensus evaluated on every supported timeframe in a single call. Use this to check whether a signal is isolated to one TF or confirmed top-down.

curl -H "Authorization: Bearer ak_..." \
  "https://api.amaneki.com/v1/consensus/btcusdt/multi-tf"

GET /v1/correlation/market

Mean pairwise Pearson correlation across every tracked symbol at the given timeframe, over the last window bars. Stateless regime label (tight ≥ 0.8, dispersed ≤ 0.3, mixed in between).

curl "https://api.amaneki.com/v1/correlation/market?timeframe=15m&window=60"

GET /v1/correlation/{symbol}

Beta of the symbol's log-returns against a reference (default BTC) plus correlation to each peer.

curl "https://api.amaneki.com/v1/correlation/ethusdt?timeframe=15m"

GET /v1/iv-gap/{symbol}

Realized vs implied vol for BTC or ETH. RV is our annualized 1-minute vol; IV is the Deribit DVOL (30-day option-implied). Gap = IV − RV. Negative gap means spot is realizing faster than options imply.

Coverage: BTC and ETH only. Deribit publishes DVOL (a 30-day implied-vol index) for those two; other symbols return 404 with a Problem Details body explaining the limit.

curl "https://api.amaneki.com/v1/iv-gap/btcusdt"

GET /v1/funding/{symbol}

Current perpetual funding rate and recent history. Source: the symbol's primary venue.

curl "https://api.amaneki.com/v1/funding/btcusdt"

GET /v1/sizing/{symbol}

Vol-targeted position size helper. Given a target annualized portfolio vol and an equity figure, returns the notional implied by the symbol's current realized vol.

curl "https://api.amaneki.com/v1/sizing/btcusdt?timeframe=15m&target_vol=0.20&equity=100000"

GET /v1/badge/{symbol}.svg

Shields.io-style SVG badge of the current regime. Drop into a README or dashboard.

<img src="https://api.amaneki.com/v1/badge/btcusdt.svg?timeframe=15m" />

POST /v1/backtest

Replay a simple rule against the in-memory feature ring (~1024 bars per series). Returns per-trade detail + summary stats. Requires an API key.

curl -X POST https://api.amaneki.com/v1/backtest \
  -H "Authorization: Bearer ak_..." \
  -H "Content-Type: application/json" \
  -d '{"symbol":"btcusdt","timeframe":"15m","rule":"long_low_exit_normal"}'

Rules: long_low_exit_normal, short_high_exit_normal, avoid_high. Optional thresholds overrides the preset.

GET /v1/symbols, /v1/timeframes, /v1/presets

Lists. Public, no key needed.

curl https://api.amaneki.com/v1/symbols

WS /v1/stream

Push every regime transition. Browsers can pass the key via query string (no custom headers): wss://api.amaneki.com/v1/stream?api_key=ak_...

{
  "type": "regime_transition",
  "symbol": "BTCUSDT",
  "timeframe": "5m",
  "ts_ms": 1776324300000,
  "from": "normal",
  "to": "high",
  "z_vol": 3.21,
  "close": 74900.12
}

Endpoints — Account

POST /v1/feedback

Submit a verdict on a past transition. Used to surface false-positive patterns back into calibration.

curl -X POST https://api.amaneki.com/v1/feedback \
  -H "Authorization: Bearer ak_..." \
  -H "Content-Type: application/json" \
  -d '{"symbol":"btcusdt","timeframe":"15m","ts_ms":1776324300000,"verdict":"false_positive","note":"wick"}'

GET /v1/feedback

List feedback submitted by this key.

curl -H "Authorization: Bearer ak_..." https://api.amaneki.com/v1/feedback

POST /v1/me/rotate-key

Issue a new key and invalidate the current one. The response is the only place the new secret is shown.

curl -X POST -H "Authorization: Bearer ak_..." \
  https://api.amaneki.com/v1/me/rotate-key

GET /v1/me/events

Audit events scoped to this key: issued, rotated, rate-limit hits, webhook deliveries.

curl -H "Authorization: Bearer ak_..." https://api.amaneki.com/v1/me/events

GET /v1/me/usage

Per-endpoint request counts for the current billing period.

curl -H "Authorization: Bearer ak_..." https://api.amaneki.com/v1/me/usage

GET /v1/me/allowlist, PUT /v1/me/allowlist

Pro Plus. Restrict this key to a subset of symbols. PUT with {"symbols": ["btcusdt","ethusdt"]}; empty list means "all tracked symbols".

curl -X PUT https://api.amaneki.com/v1/me/allowlist \
  -H "Authorization: Bearer ak_..." \
  -H "Content-Type: application/json" \
  -d '{"symbols":["btcusdt","ethusdt"]}'

GET/PUT/DELETE /v1/presets/custom

Save named threshold presets on your account. PUT body: {"name":"tight","high_enter":2.0,"low_enter":-1.8,"enter_k":3,...}. GET returns your saved presets; DELETE with ?name=tight removes one.

curl -X PUT https://api.amaneki.com/v1/presets/custom \
  -H "Authorization: Bearer ak_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"tight","high_enter":2.0,"low_enter":-1.8,"enter_k":3}'

Endpoints — Webhooks (Hobby and higher)

Per-tier subscription caps: Hobby 1 webhook, Pro 5, Pro Plus unlimited. POST beyond the cap returns 403.

POST /v1/webhooks

Register an outbound webhook. Optional filters: symbols, timeframes, to_regimes.

curl -X POST https://api.amaneki.com/v1/webhooks \
  -H "Authorization: Bearer ak_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your.app/regime",
    "symbols": ["btcusdt", "ethusdt"],
    "timeframes": ["5m", "15m"],
    "to_regimes": ["high"],
    "batch_window_seconds": 0,
    "format": "json"
  }'
FieldDefaultNotes
urlrequired. Discord webhook URLs are auto-detected and formatted
symbolsall
timeframesall
to_regimesalllow | normal | high
batch_window_seconds00-3600. Coalesce events inside this window into one delivery
formatjsonjson | discord

Response includes a one-time signing_secret. Each delivery carries an HMAC-SHA256 signature in X-Amaneki-Signature: t=<unix>,v1=<hex> over {t}.{body}.

GET /v1/webhooks

List subscriptions registered by this key.

curl -H "Authorization: Bearer ak_..." https://api.amaneki.com/v1/webhooks

DELETE /v1/webhooks/{id}

Remove a subscription. Returns 204 on success.

curl -X DELETE -H "Authorization: Bearer ak_..." \
  https://api.amaneki.com/v1/webhooks/wh_01HXYZ...

Endpoints — Sandbox

POST /v1/sandbox/key

Issue a 24-hour trial API key with Pro-Plus feature access (webhooks, custom presets, backtest, multi-timeframe consensus, symbol allowlist) but Free-tier rate limit (60 rpm). One key per source IP per 24 hours. Optional email lands the caller on the Paid-checkout notification list.

curl -X POST https://api.amaneki.com/v1/sandbox/key \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'   # email optional

The key expires on the first auth after the 24-hour mark (lazily revoked). For evaluating paid features before checkout opens.

GET /v1/regime/{symbol}/history.csv

Same data as /history, streamed as CSV for pandas / polars / spreadsheets. Accepts the same timeframe, limit, from_ms, to_ms params; X-Amaneki-Source and X-Amaneki-Count headers echo where the rows came from (memory vs postgres) and how many shipped.

curl -H "Authorization: Bearer ak_..." \
  "https://api.amaneki.com/v1/regime/btcusdt/history.csv?timeframe=15m&from_ms=$(date -v-30d +%s)000" \
  -o btc-15m-30d.csv

Endpoints — Billing (Paddle)

POST /v1/billing/paddle/checkout

Create a Paddle hosted-checkout URL. Response includes url; redirect the user there. Paddle is our Merchant of Record, so billing, taxes, and invoicing flow through their platform — your server only needs the two calls on this page plus the webhook verification.

curl -X POST https://api.amaneki.com/v1/billing/paddle/checkout \
  -H "Content-Type: application/json" \
  -d '{"tier":"pro","billing_cycle":"monthly","email":"[email protected]"}'
FieldNotes
tierhobby | pro | pro_plus
billing_cyclemonthly | annual
emailoptional; prefills Paddle checkout

Trial is fixed at 14 days (configured on the Paddle price). trial_days in the request body is ignored.

GET /v1/billing/paddle/key?transaction_id=...

Retrieve the provisioned API key for a completed checkout. One-shot: the key is only returned on first fetch. Call this from your success page (Paddle appends _ptxn=<id> to the redirect, which you pass as transaction_id).

curl "https://api.amaneki.com/v1/billing/paddle/key?transaction_id=txn_..."

POST /v1/billing/paddle/webhook

Paddle → Amaneki notification destination. Verified by the Paddle-Signature header. Not for customer use.

Endpoints — Infra

GET /v1/health

Liveness. Returns 200 if the process is up.

curl https://api.amaneki.com/v1/health

GET /v1/health/deep

Readiness. Pings the database, the Binance feed, and confirms at least one series has ticked in the last 60 seconds.

curl https://api.amaneki.com/v1/health/deep

GET /v1/metrics

Prometheus text format. Token-gated; for operators, not customers.

Errors

CodeMeaning
400Bad input (invalid symbol, malformed body)
401Missing or invalid API key
404Symbol or timeframe not tracked
429Rate limit exceeded. Retry-After header tells you how many seconds to wait
503Database unavailable (transient)

Python SDK

pip install amaneki

Published to PyPI as amaneki. Full install + codegen docs at /sdk.

from amaneki import Client

c = Client(api_key="ak_...")
snap = c.get_regime("btcusdt", timeframe="5m")
print(snap.regime, snap.z_vol, snap.seconds_in_state)

cs = c.get_consensus("btcusdt", timeframe="15m")
print(cs.consensus, f"{cs.agreed}/{cs.available}")

r = c.run_backtest("btcusdt", timeframe="15m", rule="long_low_exit_normal")
print(r.n_trades, r.total_return)

for t in c.get_history("btcusdt", from_ms=1776000000000):
    print(t.ts_ms, t.from_regime, "→", t.to_regime)

Calibration

Each symbol is calibrated independently against 180 days of its own 1-minute klines — 2,304 threshold combinations, Pareto-front selection on the (F1, alerts/day) plane. Detection lag median ~20 minutes regardless of symbol.

Macro-F1 against the smoothed percentile ground truth, by symbol and preset:

Symbolconservativebalancedaggressivealerts/day (balanced)
BTC0.370.390.415.6
ETH0.370.390.415.6
SOL0.390.430.445.0
XRP0.400.420.435.2
BNB0.380.410.425.0
DOGE0.400.430.435.1
ADA0.410.440.445.2
AVAX0.410.440.455.1
POL0.390.420.445.9
LINK0.410.450.455.0

Honest caveats: regime detection against a smoothed percentile ground truth is a noisy problem. Every symbol lands in the 0.37-0.45 band at the balanced preset. Anyone advertising F1 > 0.9 for a regime task is leaking future information into the labels.

Status

amaneki.com/status shows live health.