API
The same forecasts, for your own systems. Part of Forecaster.
Keys
Keys are made on your account page, once you are a Forecaster. A key is shown once, when it is made, and revoked there too. You can hold 5 at a time. Send it as a bearer token, or in an X-API-Key header if that suits your tooling better.
Each key can be tied to up to 2 IP addresses, set when you make it or changed later on the same page. A key with addresses answers only from those, and a call from anywhere else gets 403 with ip-not-allowed, whether or not the key is valid for everything else. A key with none answers from anywhere. Exact addresses only, no ranges.
curl -H "Authorization: Bearer ss_live_..." \ https://satorisignals.app/api/v1/forecast/bitcoin
Endpoints
GET/api/v1/forecast/{symbol}
Latest consensus forecast for one stream. The symbol is the stream's own name, for example bitcoin, eth or safetrade_csd. Accepts horizon=24h, the only horizon the network publishes.
GET/api/v1/feed?limit=80
Newest forecast per stream across the catalog, majors first. Only streams with a crowd right now. limit from 1 to 80.
GET/api/v1/accuracy/{symbol}
Forward test rollups, the agreement table and the graded archive, newest first. limit from 1 to 500, default 200.
What comes back
A forecast is what the crowd adds up to: the median, mean, tenth and ninetieth percentiles, how many neurons stood behind it, how they split around the live price, and the share that agreed with the median. The individual predictions behind the median are not served. They are the work of other people. A stream with fewer than ten predictions in the window answers with status thin and no figures. Every number is the same one the dashboard shows, refreshed on the same schedule.
{
"stream_name": "bitcoin",
"symbol": "BTC",
"horizon": "24h",
"status": "ok",
"predicted_at": "2026-09-16T09:00:00.000Z",
"target_at": "2026-09-17T09:00:00.000Z",
"live_price": 63120.5,
"consensus": { "median": 63410.2, "mean": 63398.7, "p10": 62650.0, "p90": 64120.9 },
"edge_pct": 0.46,
"direction": "UP",
"confidence": 0.81,
"counts": { "predictions": 212, "peers": 212 },
"split": { "up": 171, "down": 34, "flat": 7 }
}Limits
60 calls a minute per key. Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Past the limit you get 429 and a Retry-After in seconds. The forecasts change hourly at most, so polling faster than that buys nothing.
Access
A key answers while its owner is a Forecaster. If the subscription lapses, or the wallet drops under the threshold, the key stays but stops answering with 403, and answers again when either comes back. Holdings are read from the chain about every ten minutes, so a change there takes up to that long to show.
Errors
Every error is a JSON object with one field, error, and one of these codes.
| 400 | bad-request | A parameter the endpoint cannot use, such as a horizon other than 24h. |
| 401 | unauthorized | No key, a key we did not make, or one that was revoked. |
| 403 | ip-not-allowed | A good key used from an address it does not allow. |
| 403 | forbidden | A good key whose owner is not a Forecaster right now. |
| 404 | not-found | A stream the network does not follow. |
| 429 | rate-limited | Too many calls this minute. Retry-After says how long. |
| 503 | unavailable | We could not answer just now. Try again in a minute. |