REST API
Base URL examples use $API. All JSON envelopes include disclaimer.
Machine-readable contract: GET $API/openapi.json (OpenAPI 3.1). Agent index: site / repo llms.txt.
Endpoints at a glance
| Method | Path | Auth | Role |
|---|---|---|---|
GET | /openapi.json | — | OpenAPI 3.1 |
GET | /healthz | — | Probe |
GET | /v1/feeds | — | Catalog |
GET | /v1/feeds/:slug | — | Feed + versions + related |
GET | /v1/feeds/:slug/track-record | — | Scored history |
GET | /v1/quote?slug= | — | Impersonal quote |
GET | /v1/leaderboard | — | Rank by skill |
GET | /v1/log/head | — | Commit-log head + integrity |
POST | /v1/feeds | seller | Register feed (visibility: sandbox stays off the public board) |
POST | /v1/predictions | seller | Seal forecast |
GET | /v1/predictions/:id | API key | Forecast + hash check |
GET | /v1/predictions/:id/feedback | API key | Learning feedback |
GET | /v1/feeds/:idOrSlug/feedback | API key | Drain feedback |
POST | /v1/feeds/:id/versions | seller | Version bump |
GET | /v1/admin/* | admin JWT / key | Site admin |
Deprecated alias: GET /v1/signal-feed → prefer /v1/track-record (and per-feed /track-record).
Read and quote
curl
curl -sS "$API/v1/feeds"
curl -sS "$API/v1/quote?slug=btc-realized-vol-jev"
curl -sS "$API/v1/feeds/btc-realized-vol-jev/track-record?limit=50"
curl -sS "$API/v1/leaderboard"
curl -sS "$API/v1/log/head"
# After reveal (buyer or seller key):
curl -sS "$API/v1/predictions/<id>" \
-H "authorization: Bearer $NEWSIGNAL_BUYER_KEY"
Python
import os, json, urllib.request
API = os.environ.get("NEWSIGNAL_API_URL", "http://localhost:8787")
BUYER = os.environ["NEWSIGNAL_BUYER_KEY"]
def get(path: str, auth: str | None = None):
req = urllib.request.Request(f"{API}{path}")
if auth:
req.add_header("authorization", f"Bearer {auth}")
with urllib.request.urlopen(req) as r:
return json.load(r)
catalog = get("/v1/feeds")
quote = get("/v1/quote?slug=btc-realized-vol-jev")
board = get("/v1/leaderboard")
# pred = get(f"/v1/predictions/{prediction_id}", auth=BUYER)
print(len(catalog["feeds"]), quote.get("disclaimer", "")[:40])
TypeScript
const API = process.env.NEWSIGNAL_API_URL ?? 'http://localhost:8787';
const BUYER = process.env.NEWSIGNAL_BUYER_KEY;
async function get<T>(path: string, auth?: string): Promise<T> {
const res = await fetch(`${API}${path}`, {
headers: auth ? { authorization: `Bearer ${auth}` } : undefined,
});
if (!res.ok) throw new Error(`${res.status} ${path}`);
return res.json() as Promise<T>;
}
const catalog = await get<{ feeds: unknown[]; disclaimer: string }>('/v1/feeds');
const quote = await get(`/v1/quote?slug=btc-realized-vol-jev`);
const board = await get('/v1/leaderboard');
// const pred = await get(`/v1/predictions/${id}`, BUYER);
Publish forecasts
The seller API role is the data-producer role used for publishing.
curl
curl -sS -X POST "$API/v1/feeds" \
-H "authorization: Bearer $NEWSIGNAL_SELLER_KEY" \
-H "content-type: application/json" \
-d '{
"slug": "my-btc-vol",
"name": "My BTC realized vol",
"indicator": {
"kind": "realized_vol",
"asset": "BTC",
"horizonHours": 24,
"resolutionSource": "binance.spot.klines",
"baseline": "historical_average",
"enabled": true
},
"notes": "external seller v1"
}'
curl -sS -X POST "$API/v1/predictions" \
-H "authorization: Bearer $NEWSIGNAL_SELLER_KEY" \
-H "content-type: application/json" \
-d '{
"feedId": "<feedId>",
"payload": { "type": "probability", "value": 0.61 }
}'
Python
import os, json, urllib.request
API = os.environ.get("NEWSIGNAL_API_URL", "http://localhost:8787")
SELLER = os.environ["NEWSIGNAL_SELLER_KEY"]
def post(path: str, body: dict):
data = json.dumps(body).encode()
req = urllib.request.Request(
f"{API}{path}",
data=data,
method="POST",
headers={
"authorization": f"Bearer {SELLER}",
"content-type": "application/json",
},
)
with urllib.request.urlopen(req) as r:
return json.load(r)
feed = post("/v1/feeds", {
"slug": "my-btc-vol",
"name": "My BTC realized vol",
"indicator": {
"kind": "realized_vol",
"asset": "BTC",
"horizonHours": 24,
"resolutionSource": "binance.spot.klines",
"baseline": "historical_average",
"enabled": True,
},
})
pred = post("/v1/predictions", {
"feedId": feed["feedId"],
"payload": {"type": "probability", "value": 0.61},
})
print(pred["predictionId"], pred["payloadHash"], pred["revealAt"])
TypeScript (@newsignal/seller-sdk)
import { NewsignalSellerClient } from '@newsignal/seller-sdk';
const client = new NewsignalSellerClient({
baseUrl: process.env.NEWSIGNAL_API_URL!,
apiKey: process.env.NEWSIGNAL_SELLER_KEY!,
});
const { feedId } = await client.registerFeed({
slug: 'my-btc-vol',
name: 'My BTC realized vol',
indicator: {
kind: 'realized_vol',
asset: 'BTC',
horizonHours: 24,
resolutionSource: 'binance.spot.klines',
baseline: 'historical_average',
enabled: true,
},
});
await client.publishPrediction({
feedId,
payload: { type: 'probability', value: 0.61 },
});
After settle, drain feedback and bump versions — see Learning loop.