QuantX402 is a pay-per-call AI price forecast API. Every hour it runs the open-source Kronos candlestick model on BTC-USD and ETH-USD and serves the result as an agent-readable JSON fact list. The output is an experimental model signal, not a calibrated prediction. Agents pay per call with x402 in USDC on Base or Solana mainnet. No account, no API key.
- Base URL:
https://quantx402.app - OpenAPI 3.1: https://quantx402.app/openapi.json
- x402 discovery: https://quantx402.app/.well-known/x402
- For LLMs: https://quantx402.app/llms.txt and https://quantx402.app/llms-full.txt
- Symbols:
BTC-USD,ETH-USD. Timeframes:1h. Horizon: 24 candles.
Probabilistic model output for research and education. Not financial advice. Past results do not guarantee future results.
Model status
Model status: experimental, not calibrated. We backtested the raw Kronos-small output on past BTC and ETH candles. The raw model did not show a reliable directional edge, its raw 80% band was much too narrow, and its raw share of paths finishing higher overstated confidence. So the forecast is an experimental model signal, not a prediction you can rely on. The changes rolling out now:
- The range is re-centred on the last close and widened to match historical volatility. Treat it as a volatility-based range, not a model promise.
band_calibratedstaysfalse. - The expected move is shrunk to zero: no magnitude call is published.
- The raw share of paths finishing higher is replaced by a direction plus a confidence bucket that is never "high" from Kronos alone. Raw path counts are not probabilities or odds.
- Every forecast is scored after its 24-hour window and published, misses included, in the free track record.
Informational, not financial advice.
When to use this API
Use QuantX402 when an agent wants an experimental, checkable model signal for BTC or ETH over the next 24 hours: a direction with a confidence label, a volatility-based range and an invalidation level, with provenance and a public track record. Good fits: research agents that want a Kronos signal as one input among others, bots that log a model view next to prediction-market prices (p_close_above is a raw path share, not odds), and dashboards that chart the range. Not a fit: anything that needs a proven edge, reliable direction calls, calibrated probabilities, tick-level execution signals, or assets other than the listed symbols.
Endpoints
| Endpoint | What it returns | Price |
|---|---|---|
GET /api/v1/forecast?symbol=BTC-USD&tf=1h |
Latest Kronos Forecast fact list | $0.02 per call (x402) |
GET /api/v1/signal?symbol=BTC-USD&tf=1h |
Signal Blend: Kronos + market context, stance and reasons | $0.03 per call (x402) |
GET /api/v1/sample?symbol=BTC-USD&tf=1h |
Free forecast preview, at least 2 hours old | Free |
GET /api/v1/signal/sample?symbol=BTC-USD&tf=1h |
Free Signal Blend preview, at least 2 hours old | Free |
GET /api/v1/track-record |
Every stored forecast and its scored outcome | Free |
GET /api/v1/chart?symbol=BTC-USD&tf=1h |
Per-step percentiles for charting, at least 2 hours old | Free |
GET /api/v1/health |
Data freshness, worker status, payment network | Free |
Kronos Forecast: GET /api/v1/forecast ($0.02)
The newest hourly Kronos-small run: 30 sampled 24-hour price paths from the last 360 closed 1h candles, summarized as facts. Experimental and not calibrated (see Model status); field details are in /openapi.json and may change as the calibration rolls out. The response has the same fields as the free sample below (without sample and delay_note) plus per-step percentiles.
Key fields:
direction: UP if prob_up >= 0.6, DOWN if <= 0.4, else NEUTRAL.prob_up(raw): share of sampled paths whose final close is abovelast_close. A count of model samples, not a probability or odds; being replaced by a confidence bucket.expected_move_pct: the model's move estimate; being shrunk to zero because the raw median move was not reliable.band_80_pct/expected_range: the range in percent and in price. Treat it as a volatility-based range, not a calibrated 80% interval.band_calibrated: false. The range is not calibrated against outcomes yet.invalidation_level: for UP, the 10th percentile of path lows; for DOWN, the 90th percentile of path highs.p_close_above: raw share of paths finishing above nearby round strikes. Not a probability; don't treat it as odds against prediction-market prices.stale: true if one candle behind. Two or more behind returns503 FORECAST_STALEand is not charged.
Signal Blend: GET /api/v1/signal ($0.03)
The latest Kronos model signal merged with current market context (24h change, momentum agreement, invalidation check) into a stance of LEAN_UP, LEAN_DOWN or NO_EDGE, with plain-English reasons. A stance is a summary of the inputs, not a claim of edge. The sentiment slot is null until a licensed source is added.
Free endpoints
/api/v1/sample, /api/v1/signal/sample and /api/v1/chart serve a run at least 2 hours old. /api/v1/track-record (also at /track-record) lists every stored forecast and, once its 24-hour window closes, its scored outcome, misses included. /api/v1/health reports freshness.
Quickstart
Free preview, no payment:
curl "https://quantx402.app/api/v1/sample?symbol=BTC-USD&tf=1h"
See the payment challenge on the paid endpoint:
curl -i "https://quantx402.app/api/v1/forecast?symbol=BTC-USD&tf=1h"
# HTTP/2 402 + PAYMENT-REQUIRED: <base64 JSON>
Pay automatically from Node with the x402 fetch wrapper (wallet must hold USDC on Base; for Solana, register ExactSvmScheme from @x402/svm/exact/client for solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp):
// npm i @x402/fetch @x402/core @x402/evm viem
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
client.register("eip155:8453", new ExactEvmScheme(privateKeyToAccount(process.env.EVM_PRIVATE_KEY)));
const payFetch = wrapFetchWithPayment(fetch, client);
const res = await payFetch("https://quantx402.app/api/v1/forecast?symbol=BTC-USD&tf=1h");
const facts = await res.json();
console.log(facts.direction, facts.prob_up, facts.band_80_pct, facts.invalidation_level);
The Guide has a complete, tested client.
How to pay with x402
GETa paid endpoint. The server answers HTTP 402 with aPAYMENT-REQUIREDheader: base64-encoded JSON listing the accepted payment options.- Pick an option:
exactscheme, USDC on Base (eip155:8453, sign an EIP-3009 transfer authorization) or USDC on Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp, sign a USDC transfer transaction).amounthas 6 decimals, so 20000 = $0.02, paid to that option'spayTo. - Retry the same request with the
PAYMENT-SIGNATUREheader (base64 JSON). Legacy v1X-PAYMENTheaders are also accepted. - The server verifies through the Coinbase CDP facilitator, returns 200 with the data, and settles on-chain. The
PAYMENT-RESPONSEheader carries the settlement result. Failed responses are never settled.
Decoded PAYMENT-REQUIRED header for /api/v1/forecast (captured 2026-10-11T23:12Z, before Solana was enabled; the live header now also lists a Solana option):
{
"x402Version": 2,
"error": "Payment required",
"resource": {
"url": "https://quantx402.app/api/v1/forecast?symbol=BTC-USD&tf=1h",
"description": "Kronos Forecast: the latest hourly Kronos-small run as an agent-readable fact list (direction, confidence label, volatility-based range, invalidation level, per-step percentiles). Experimental model signal, not calibrated; full track record free at /api/v1/track-record. Informational, not financial advice.",
"mimeType": "application/json",
"serviceName": "QuantX402",
"tags": [
"crypto",
"forecast",
"kronos",
"bitcoin",
"ethereum",
"time-series"
]
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "20000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x2b79541911a436a83074eb3a38a920042524db96",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USD Coin",
"version": "2"
}
}
],
"extensions": {
"bazaar": {
"info": {
"input": {
"type": "http",
"queryParams": {
"symbol": "BTC-USD",
"tf": "1h"
},
"method": "GET"
},
"output": {
"type": "json",
"example": {
"symbol": "BTC-USD",
"direction": "UP",
"prob_up": 0.933,
"expected_move_pct": 0.737,
"band_80_pct": [
0.39,
1.418
],
"invalidation_level": 82954.2
}
}
}
}
}
}
Example responses
These are real responses captured from the live API at 2026-10-11T23:12Z. Values change every hour; fields may be added over time (see /openapi.json).
GET /api/v1/sample?symbol=BTC-USD&tf=1h
{
"sample": true,
"delay_note": "Free sample, at least 2 hours old. Live forecast: /api/v1/forecast ($0.02)",
"forecast_id": 11,
"as_of": "2026-10-11T21:00:00Z",
"model": "Kronos-small",
"venue": "Coinbase",
"symbol": "BTC-USD",
"prob_up": 0.933,
"sampling": {
"T": 1,
"seed": 42,
"paths": 30,
"top_p": 0.9
},
"direction": "UP",
"timeframe": "1h",
"confidence": "MEDIUM",
"disclaimer": "Probabilistic model output for research and education. Not financial advice. Past results do not guarantee future results.",
"last_close": 83442.2,
"asset_class": "crypto",
"band_80_pct": [
0.318,
1.555
],
"data_source": "Coinbase Exchange public candles (closed bars only)",
"horizon_end": "2026-10-12T21:00:00Z",
"context_bars": 360,
"generated_at": "2026-10-11T22:12:38Z",
"horizon_bars": 24,
"expected_range": [
83707.42,
84739.7
],
"band_calibrated": false,
"confidence_rule": "v1: single model (Kronos-small). MEDIUM if |prob_up-0.5|>=0.3, else LOW. HIGH is disabled until calibration.",
"calibration_note": "80% band is raw model spread, not yet checked against outcomes. Treat as uncalibrated.",
"expected_move_pct": 0.847,
"invalidation_level": 82475.74,
"hist_vol_over_horizon_pct": 1.336
}
GET /api/v1/signal/sample?symbol=BTC-USD&tf=1h
{
"sample": true,
"delay_note": "Free preview on a Kronos run at least 2 hours old. Latest: /api/v1/signal ($0.03)",
"product": "signal-blend",
"forecast_id": 11,
"symbol": "BTC-USD",
"timeframe": "1h",
"as_of": "2026-10-11T21:00:00Z",
"horizon_end": "2026-10-12T21:00:00Z",
"stance": "LEAN_UP",
"odds_up": 0.933,
"direction_kronos": "UP",
"confidence": "MEDIUM",
"expected_range": [
83707.42,
84739.7
],
"band_80_pct": [
0.318,
1.555
],
"invalidation_level": 82475.74,
"invalidated_now": false,
"reasons": [
"Kronos: 93% of 30 sampled paths finish above $83,442 by 2026-10-12T21:00:00Z (median move +0.847%).",
"Kronos confidence is medium; the 80% band (0.318% to 1.555%) is not calibrated yet.",
"Market: spot $83,637, +0.77% over 24h (up momentum), +0.23% since the forecast's last close.",
"Sentiment/news: not connected yet (no licensed source), so it doesn't affect the stance."
],
"inputs": {
"kronos": {
"model": "Kronos-small",
"last_close": 83442.2,
"prob_up": 0.933,
"expected_move_pct": 0.847,
"sampling": {
"T": 1,
"seed": 42,
"paths": 30,
"top_p": 0.9
},
"data_source": "Coinbase Exchange public candles (closed bars only)",
"generated_at": "2026-10-11T22:12:38Z"
},
"market": {
"spot_usd": 83637,
"change_24h_pct": 0.77,
"as_of": "2026-10-11T23:12:43.290Z",
"stale": false,
"source": "coingecko",
"attribution": "Data provided by CoinGecko",
"momentum_24h": "UP",
"move_since_forecast_pct": 0.23
},
"sentiment": {
"value": null,
"status": "not_connected",
"note": "Slot reserved for a licensed news/sentiment source."
}
},
"agreement": "ALIGNED",
"blend_rule": "v1: stance follows the Kronos direction unless price already crossed the invalidation level (NO_EDGE), or Kronos confidence is LOW and 24h momentum doesn't agree (NO_EDGE). Momentum: 24h change above +0.25% = UP, below -0.25% = DOWN, else FLAT.",
"disclaimer": "Probabilistic model output for research and education. Not financial advice. Past results do not guarantee future results."
}
GET /api/v1/track-record (first entry of recent shown)
{
"product": "track-record",
"note": "No forecast has been scored yet. Each run is scored after its 24-hour window closes.",
"summary": [
{
"symbol": "BTC-USD",
"timeframe": "1h",
"model": "Kronos-small",
"forecasts": 5,
"scored": 0,
"hit_rate": null,
"band_80_coverage": null,
"first_as_of": "2026-10-11T17:00:00Z",
"last_as_of": "2026-10-11T22:00:00Z",
"next_score_due": "2026-10-12T17:00:00Z"
},
{
"symbol": "ETH-USD",
"timeframe": "1h",
"model": "Kronos-small",
"forecasts": 5,
"scored": 0,
"hit_rate": null,
"band_80_coverage": null,
"first_as_of": "2026-10-11T17:00:00Z",
"last_as_of": "2026-10-11T22:00:00Z",
"next_score_due": "2026-10-12T17:00:00Z"
}
],
"disclaimer": "Probabilistic model output for research and education. Not financial advice. Past results do not guarantee future results.",
"recent": [
{
"id": 17,
"symbol": "BTC-USD",
"timeframe": "1h",
"as_of": "2026-10-11T22:00:00Z",
"horizon_end": "2026-10-12T22:00:00Z",
"direction": "UP",
"prob_up": 0.8669999837875366,
"expected_move_pct": 0.8920000195503235,
"last_close": 83550.02,
"realized_move_pct": null,
"direction_hit": null,
"inside_band_80": null
}
]
}
GET /api/v1/health
{
"status": "ok",
"time": "2026-10-11T23:12:50Z",
"latest": [
{
"symbol": "BTC-USD",
"tf": "1h",
"as_of": "2026-10-11T22:00:00Z",
"age_minutes": 13,
"stale": false,
"lag": 0
},
{
"symbol": "ETH-USD",
"tf": "1h",
"as_of": "2026-10-11T22:00:00Z",
"age_minutes": 13,
"stale": false,
"lag": 0
}
],
"worker": {
"last_run_started": "2026-10-11T23:06:25Z",
"last_run_ok": true,
"last_error": null,
"last_success_finished": "2026-10-11T23:09:38Z",
"minutes_since_success": 3
},
"db": "ok",
"x402": {
"network_mode": "mainnet",
"ready": true,
"facilitator": "cdp",
"networks": [
"eip155:8453"
]
},
"version": "8d31bd3",
"coingecko": {
"month": "2026-10",
"calls": 7,
"failed": 0,
"cap": 8000,
"pct_of_cap": 0.1
}
}
Errors
Errors are JSON with a machine-readable code and a message, and are never charged:
{
"error": {
"code": "INVALID_SYMBOL",
"message": "Supported symbols: BTC-USD, ETH-USD"
},
"disclaimer": "Probabilistic model output for research and education. Not financial advice. Past results do not guarantee future results."
}
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_SYMBOL / INVALID_TIMEFRAME |
Unsupported symbol or timeframe |
| 402 | (x402) | Payment required; see the PAYMENT-REQUIRED header |
| 404 | NO_FORECAST / NOT_FOUND |
No forecast stored yet, or unknown API path |
| 503 | FORECAST_STALE |
Newest forecast is 2+ candles old |
| 503 | NO_SAMPLE / DB_UNAVAILABLE / PAYMENTS_UNAVAILABLE |
Temporary outage; retry later |
Limits
- Forecasts update hourly; calling more often returns the same run until the next candle closes.
- No published rate limit today. Please keep automated polling to about once per minute per symbol.
- The model is experimental and not calibrated (
band_calibrated: false). See Model status.
Versioning and deprecation
The API is versioned in the path (/api/v1). Fields may be added to v1 responses without notice; existing fields will not be removed or change meaning within v1. Breaking changes will ship as /api/v2, and v1 will keep working for at least 90 days after a v2 announcement on this page, in /llms.txt, and on X (@fdwa_ai).
Disclaimer
Probabilistic model output for research and education. Not financial advice. Past results do not guarantee future results. Kronos is an open-source model (MIT) by its original authors; QuantX402 is not affiliated with them.