/docs/examples
Code examples
curl, Python and JavaScript, run against a test copy of the service before publishing.
Every example here ran in the rehearsal against a test copy of the service on 2 Oct 2026; the outputs below are from that run. Set ERS_API_KEY to your key; ERS_BASE defaults to https://entryriskscore.com. None of this tells anyone to trade: the code reads a measurement and leaves every decision to you.
curl
#!/bin/sh
# First request: the current state of BTCUSDT, all profiles and sides.
# ERS_BASE defaults to the live service; ERS_API_KEY comes from the dashboard (API & MCP).
BASE="${ERS_BASE:-https://entryriskscore.com}"
curl -s "$BASE/api/v1/state?symbol=BTCUSDT&profile=scalp&side=LONG" -H "X-API-Key: $ERS_API_KEY"
echoPython (requests): one request
"""One request with Python requests: the scalp LONG state of BTCUSDT."""
import os
import requests
BASE = os.environ.get('ERS_BASE', 'https://entryriskscore.com')
r = requests.get(f'{BASE}/api/v1/state', params={'symbol': 'BTCUSDT', 'profile': 'scalp', 'side': 'LONG'},
headers={'X-API-Key': os.environ['ERS_API_KEY']}, timeout=10)
r.raise_for_status()
body = r.json()
row = body['data'][0]
print(row['symbol'], row['side'], row['profile'], row['status'], row['score'], row['as_of'])
print('meaning:', body['meta']['score_meaning'])
print('next update:', body['meta']['next_update_at'])Output:
BTCUSDT LONG scalp NORMAL 9.2 2026-10-02T08:00:00Z meaning: Risk Score N/100 = riskier to enter than N% of that coin's own moments (history up to 90 days). Not a probability. next update: 2026-10-02T08:05:00Z
Python: polling loop with next_update_at and Retry-After
"""Polling loop that respects next_update_at and Retry-After (one request per 5-minute update)."""
import os
import time
from datetime import datetime, timezone
import requests
BASE = os.environ.get('ERS_BASE', 'https://entryriskscore.com')
KEY = os.environ['ERS_API_KEY']
ROUNDS = int(os.environ.get('ERS_ROUNDS', '0')) # 0 = run until stopped
def wait_until(iso_utc, margin_s=20):
if not iso_utc:
return 300
due = datetime.strptime(iso_utc, '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).timestamp()
return max(5, due + margin_s - time.time())
n = 0
while True:
r = requests.get(f'{BASE}/api/v1/high-risk', params={'profile': 'scalp'}, headers={'X-API-Key': KEY}, timeout=10)
if r.status_code == 429:
pause = int(r.headers.get('Retry-After', '60'))
print('429', r.json()['error']['code'], '-> waiting', pause, 's')
time.sleep(pause)
continue
r.raise_for_status()
body = r.json()
names = [f"{x['symbol']} {x['side']} {round(x['score'])}/100" for x in body['data']]
print(body['meta'].get('next_update_at'), 'HIGH now:', ', '.join(names) or 'none')
n += 1
if ROUNDS and n >= ROUNDS:
break
time.sleep(wait_until(body['meta'].get('next_update_at')))Output (one round):
2026-10-02T08:05:00Z HIGH now: 1000PEPEUSDT LONG 93/100, ARBUSDT SHORT 90/100, BTCUSDT SHORT 84/100, ENAUSDT SHORT 92/100, ETHUSDT LONG 88/100, LINKUSDT SHORT 82/100, NEARUSDT LONG 81/100, SOLUSDT LONG 82/100, SOLUSDT SHORT 91/100, TRXUSDT SHORT 80/100
Risk check before your own entry logic (Python)
Returns the measured state of one coin and side. It does not decide anything: your own rules do.
"""A risk check to run before your own entry logic. It returns the measured state only; it is not a recommendation to
trade and decides nothing for you."""
import os
import requests
BASE = os.environ.get('ERS_BASE', 'https://entryriskscore.com')
def entry_risk(symbol, side, profile='scalp', key=None):
r = requests.get(f'{BASE}/api/v1/state', params={'symbol': symbol, 'side': side, 'profile': profile},
headers={'X-API-Key': key or os.environ['ERS_API_KEY']}, timeout=10)
r.raise_for_status()
body = r.json()
row = body['data'][0] if body['data'] else {}
return {'status': row.get('status'), 'score': row.get('score'), 'as_of': row.get('as_of'),
'health': body['meta']['health'], 'meaning': body['meta']['score_meaning']}
if __name__ == '__main__':
print(entry_risk('ETHUSDT', 'LONG'))Output:
{'status': 'HIGH', 'score': 88.2, 'as_of': '2026-10-02T08:00:00Z', 'health': 'OK', 'meaning': "Risk Score N/100 = riskier to enter than N% of that coin's own moments (history up to 90 days). Not a probability."}Risk check before your own entry logic (JavaScript, Node 18+)
// A risk check before your own entry logic (Node 18+, built-in fetch). Returns the measured state only.
const BASE = process.env.ERS_BASE || 'https://entryriskscore.com';
export async function entryRisk(symbol, side, profile = 'scalp', key = process.env.ERS_API_KEY) {
const url = `${BASE}/api/v1/state?symbol=${symbol}&side=${side}&profile=${profile}`;
const r = await fetch(url, { headers: { 'X-API-Key': key } });
if (r.status === 429) {
return { error: 'rate_limited', retryAfterS: Number(r.headers.get('retry-after') || 60) };
}
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const body = await r.json();
const row = body.data[0] || {};
return { status: row.status, score: row.score, asOf: row.as_of, health: body.meta.health };
}
console.log(await entryRisk('ETHUSDT', 'LONG'));Output:
{
status: 'HIGH',
score: 88.2,
asOf: '2026-10-02T08:00:00Z',
health: 'OK'
}Verify a ledger day's SHA-256 (Python)
"""Verify a published ledger day: the SHA-256 of the exact bytes must equal the published hash, and the entry must
point to the previous entry's hash."""
import hashlib
import os
import sys
import requests
BASE = os.environ.get('ERS_BASE', 'https://entryriskscore.com')
listing = requests.get(f'{BASE}/api/v1/public/ledger', timeout=10).json()
entries = listing.get('entries') or []
if not entries:
print('No ledger entries published yet.')
sys.exit(0)
day = sys.argv[1] if len(sys.argv) > 1 else entries[0]['day']
raw = requests.get(f'{BASE}/api/v1/public/ledger/{day}.json', timeout=10).content
published = next(e['sha256'] for e in entries if e['day'] == day)
print(day, 'sha256 ok' if hashlib.sha256(raw).hexdigest() == published else 'MISMATCH')Output in the rehearsal (no entry existed yet; the first one publishes on 3 Oct 2026 at 00:10 UTC):
No ledger entries published yet.