/docs/api
API reference
Every endpoint with its parameters, an example answer and the meaning of each field.
Endpoints
Base URL https://entryriskscore.com/api/v1. All responses are JSON: {"data": …, "meta": {…}}. meta carries the engine version, the last engine run, health (OK or LATE), your plan and the Data Notice.
| Method | Path | Access | Returns |
|---|---|---|---|
| GET | /state | key | current state per symbol, profile and side |
| GET | /high-risk | key | current HIGH rows only |
| GET | /components | key | composite and the three component values and percentiles |
| GET | /history | key | published states of one symbol over time |
| GET | /ledger | key | daily ledger entries |
| GET | /meta | public | universe, trial coins, profiles, statuses, quotas |
| GET | /public/ledger | public | published ledger entries with their hashes |
| GET | /public/ledger/YYYY-MM-DD.json | public | one entry, byte for byte as hashed |
| GET | /health | public | engine freshness |
GET /state
Parameters (all optional): symbol (e.g. BTCUSDT), profile (scalp · intraday · daily), side (LONG · SHORT). Without a symbol you get every coin of your plan.
{
"data": [{
"symbol": "BTCUSDT", "profile": "scalp", "side": "LONG",
"status": "HIGH", "score": 86.4,
"base_rate": 0.0412, "base_n": 8120,
"as_of_ms": 1790000000000, "as_of": "2026-10-05T14:35:02Z"
}],
"meta": { "health": "OK", "plan": "full", "score_definition": "v1.0-rank",
"score_meaning": "Risk Score N/100 = riskier to enter than N% of that coin's own moments (history up to 90 days). Not a probability.", … }
}status is HIGH, ELEVATED, NORMAL, MEASURING (Intraday and Daily SHORT: no score, base risk only), WARMING (not enough history) or STALE (data late; score held). Treat anything that is not a score as unknown — never as NORMAL. score is the Risk Score: 86.4 is shown as Risk Score 86/100 = riskier to enter than 86% of that coin's own moments (meta.score_meaning). Not a probability. base_rate is the share of the coin's last 90 days that touched the adverse level, with base_n moments behind it.
GET /high-risk
Optional profile and side. Returns only rows whose status is HIGH — handy for a single request per cycle.
GET /components
Optional symbol and side. For each coin and side: score, composite, components_n and the three components, each with its raw value and its percentile. Percentiles are side-signed: higher means more entry risk for that side.
GET /history
symbol (required), side, from_ms, to_ms (default: the last 24 h, at most 31 days) and limit (default 288, at most 2,000). Rows are in ascending time: at, side, status, score. A LONG score applies to Scalp, Intraday and Daily; a SHORT score to Scalp.
GET /ledger
from_day and to_day as YYYY-MM-DD (default: the last 30 days). Each entry has the day, the publication time, its SHA-256 and the payload: per profile and side the moments, label coverage, HIGH and REST counts and rates, per-state counts and the difference in percentage points. Each payload names the hash of the previous entry (prev_sha256), so the whole chain can be checked.
GET /meta and GET /health
No key needed. /meta lists the 19 coins, the 10 trial coins, the profiles and the quotas. /health says whether the last engine run is fresh (OK) or older than 10 minutes (LATE).
Fields and units
The same table is served by GET /api/v1/meta (fields), so a program can read it.
| Field | Meaning and unit |
|---|---|
| symbol | Binance USDT-M perpetual, e.g. BTCUSDT. |
| profile | Holding period: scalp = 60 min (adverse move 1%), intraday = 8 h (2%), daily = 24 h (3%). |
| side | LONG or SHORT. Both sides are scored for all three profiles (score v1.1). |
| status | HIGH (score >= 80), ELEVATED (60-79), NORMAL (< 60), MEASURING (legacy v1.0 value, no longer used), WARMING (not enough history yet), STALE (no fresh data for this symbol). |
| score | Risk Score 0-100: riskier to enter than score% of the coin's own moments (history up to 90 days). Not a probability. null when not scored. |
| base_rate | Share 0-1 of this coin's measured moments that were followed by the adverse move within the profile's horizon (HIGH or not). |
| base_n | Number of measured moments behind base_rate. |
| history_n | Number of 5-minute snapshots in the percentile history behind the score. |
| as_of_ms | Measurement time, epoch milliseconds UTC. |
| as_of | Measurement time, ISO 8601 UTC. |
| composite | Mean of the available component percentiles (0-1) before ranking. |
| components_n | Number of components available for this measurement (0-3). |
| components.volatility.value | atr1_pct: 1-hour ATR as a percentage of price (%). |
| components.crowding.value | funding_pctile: funding-rate percentile 0-1 within the coin's own history. |
| components.extension_4h.value | ext4h_atr1h: the 4-hour price move in units of 1-hour ATR (signed). |
| components.*.percentile | Side-signed percentile 0-1 within the coin: higher = riskier for that side. |
| at_ms / at | History row time (epoch ms / ISO 8601 UTC). |
| meta.next_update_ms / next_update_at | as_of of the newest measurement + 300 s: when the next scores are due. |
| meta.health | OK when the newest measurement is at most 12 min old and the engine ran recently, else LATE. |
| meta.score_meaning | One-sentence definition of the score, to pass on with the numbers. |
| ledger.entry | The published daily ledger payload; sha256 is the SHA-256 of its exact JSON bytes. |
Update cycle in every response
"meta": {
"next_update_ms": 1790855400000,
"next_update_at": "2026-10-02T07:45:00Z",
"poll_hint": "Scores change every 5 minutes; poll once per 5 minutes after next_update_at.",
"score_meaning": "Risk Score N/100 = riskier to enter than N% of that coin's own moments (history up to 90 days). Not a probability.",
"rank_meaning": "deprecated — use score_meaning"
}OpenAPI
An OpenAPI 3.1 document with every public endpoint, parameters, authentication, errors and examples: /api/v1/openapi.json. Session-only dashboard routes are not part of the public API.