Crash odds for covered SOL tokens, one request at a time.
https://api.hodlodds.com
x402 v2
USDC on Solana or Base
Recomputed every 60 s
Fresh or free
0.04 means about 4 in 100 tokens like this one lose 90% or more of their price within the next 60 minutes. Higher means riskier, but a low number does not mean safe: smaller or slower drops are not counted, and the odds change minute by minute.
On this page
Quickstart for agents
Inspect the metadata
Check /v1/status and /v1/meta first.
A live feed alone does not mean paid access is enabled: require public_beta and payments.ready from metadata.
Before launch, Cloudflare Access may also require owner or service-token access; an Access login page is not an x402 response.
Set your payment limits
Use a dedicated local payer with USDC on the exact advertised Solana network. Obtain the expected payment recipient independently,
then allow only that recipient, USDC mint, network and a fixed per-call maximum. These examples explicitly authorize mainnet risk calls up to $0.01;
for the board use its advertised price with a consciously raised cap. Devnet uses different USDC and network identifiers.
Choose a client and keep the receipt
Use the official x402 2.25.0 client for the selected scheme: Solana exact or Base EIP-3009 exact authorization. Base signing needs no token approval or SPL Memo. Pin the network, USDC contract, recipient and maximum total before signing. Never choose an offered network automatically just because it appears first. The examples below explicitly target Solana; Base customers use the SDK's EVM signer and the Base option advertised by the service.
The Python imports and version were checked against the official x402 2.25.0 wheel and client source.
The TypeScript package versions and interfaces could not be verified in the offline reference bundle: the example is a review starting point,
not a tested version pin. Validate compatible official packages, pin them and retain the lockfile before funding a client.
Do not assume their version equals the Python version.
The SDK signs locally. HodlOdds never receives your private key. The facilitator supplies the transaction fee payer.
Store payment receipts; do not log signed payment payloads or automatically retry after an ambiguous result.
The examples use each library's payment client; they do not construct the x402 payment protocol themselves.
Machine-readable contract: OpenAPI 3.1.
Agent overview: llms.txt. Response examples in the contract are explicitly illustrative data.
The forecast ends at horizon_end, not 60 minutes after your request.
These clients request fresh answers only and never fall back automatically. To opt in to last-known odds,
explicitly request /v1/risk/{mint}/last and set the payment cap to its advertised price
(default 2_000 USDC atomic units). Inspect stale, age_s and
horizon_remaining_s before using the response.
How to read a score
HodlOdds estimates whether a completed one-minute close in SOL will be at least 90% below the reference close within the displayed 60-minute forecast window. It does not measure every kind of loss or whether a token can be sold.
The independent trading system operated by the publisher may trade these tokens. It receives no customer searches, API purchases or order flow. Payment does not change a score.
Freshness
Minute closesCompleted one-minute bars
Scored ~20 s laterComputation and publication can delay availability
Until the next updateRefresh once per minute
Scores are recomputed every 60 seconds, about 20 seconds after each minute closes, from completed one-minute bars up to as_of. Each score covers the 60 minutes after its as_of time and is valid only until the next update; the odds for the same token can rise sharply from one minute to the next. Scoring starts around :20; computation and publication can delay availability. For decisions, refresh immediately before acting and once per minute for continuous monitoring, checking as_of for a new minute. The API freshness cutoff is separate: by default, data becomes stale more than 120 seconds after issued_at or after expires_at. A new request does not restart the forecast window.
Historical confidence
Confidence describes how closely historical predictions in this probability range matched what happened, and how much evidence backs that. It is not a guarantee for this token.
Historical validation of weekly BF refits, September 1 through October 14, 2026 excluding September 20; already-seen data, not measured calibration of the frozen serving fit.
The additive confidence field uses rule hodlodds.confidence.v1.
It never changes the probability, rank, alert threshold or feed freshness. A confidence level is an ordinal presentation label, not a statistical confidence interval or a claim that a token can be sold.
Let error be the absolute difference between observed incidence and mean prediction, and let
tol = max(0.02, 0.25 × pred). Relative error is error / pred;
when pred is zero it is zero only if observed is also zero, otherwise infinite.
Approximate positives are n × observed.
High: at least 100 positive landmarks, error ≤ tol/2 and relative error ≤25%.
Medium: otherwise, at least 20 positive landmarks, error ≤ tol and relative error ≤50%.
Low: otherwise, including missing or invalid evidence.
The relative limits prevent a small absolute error from hiding an incidence rate much larger than predicted.
Direction says historically under-predicted or over-predicted only when error > tol/2 or relative error >25%.
Tokens younger than 120 minutes, or with unknown age, cannot receive high confidence.
The historical bands include young tokens, but do not validate age-specific calibration or complete feature history.
Non-SOL rows always receive experimental, with no SOL validation statistics attached.
All counts below are landmarks, which can repeat the same mint or crash. Approximate positives are not independent incidents.
Per-band distinct-mint counts and confidence intervals are unavailable. The levels below assume a known age of at least 120 minutes.
Probability range
Landmarks
Mean predicted
Observed
Approx. positives
Level
Direction
0–0.5%
1,379,849
0.0240%
0.0348%
480
medium
historically under-predicted
0.5–1%
33,234
0.7277%
1.3300%
442
low
historically under-predicted
1–2%
43,010
1.4784%
2.4064%
1,035
low
historically under-predicted
2–5%
77,515
3.3702%
3.7954%
2,942
high
None
5–10%
54,037
7.0499%
5.6313%
3,043
medium
historically over-predicted
10–20%
30,095
14.0440%
11.3740%
3,423
medium
historically over-predicted
20–40%
17,591
27.8544%
27.3094%
4,804
high
None
40–70%
11,918
53.2333%
63.6684%
7,588
medium
historically under-predicted
70–100%
7,160
83.8896%
85.1816%
6,099
high
None
This is the frozen reference evidence table, also available with its source hash and rule in /v1/meta.
New response rows carry their own publisher-supplied evidence. Old snapshots without the additive field remain valid and have no inferred confidence level.
On the separate last-known route, stale data applies the one-level downgrade described below; the original evidence and probability stay unchanged.
Coverage
Coverage is limited to supported, active SOL-quoted pump.fun graduates. Non-SOL pairs are experimental rankings: mid-range scores historically underpredicted incidence. Their scores are returned free with HTTP 404, never sold as probabilities.
Endpoints
Routes and prices
GET
/v1/status
Free
Feed state, incidents and uptime
Parameters and filters
Parameter
Details
—
No parameters.
Key response fields
state
Current feed state.
incidents
Feed interruptions.
uptime_30d_pct
Feed uptime over the observed part of 30 days.
GET
/v1/meta
Free
Model, coverage, prices and payment network
Parameters and filters
Parameter
Details
—
No parameters.
Key response fields
public_beta
Whether paid access is enabled; also require payments.ready.
payments.ready
Payment readiness.
payments.prices
Current prices.
GET
/v1/coverage/{mint}
Free
Observed stage and reason for coverage, including unknown mints
Parameters and filters
Parameter
Details
mint
Token mint.
Key response fields
stage
Observed coverage stage.
reason
Reason for coverage.
as_of
Observation time; an old observation is not a fresh probability.
Free mint coverage
GET /v1/coverage/{mint} returns hodlodds.coverage.v1, without payment headers and cacheable for 60 seconds.
The stages are covered, experimental_non_sol, graduated_inactive, bonding_curve and unknown.
Read the reason and observation time as_of: an old observation is not a fresh probability, and an inactive label does not prove there were no trades elsewhere.
Unknown means not observed in the bounded directory, not that the mint does not exist. Last trade time and graduation may be unknown; curve tokens have no crash probability.
A risk route's free 404 includes the same coverage fields, plus its error and any available experimental information.
GET
/v1/risk/{mint}
$0.01 USDC
One covered SOL token
Parameters and filters
Parameter
Details
mint
Token mint.
Key response fields
as_of
Completed one-minute bars up to this time (UTC epoch seconds).
issued_at
Snapshot issue time (UTC epoch seconds).
expires_at
Fresh expiry (UTC epoch seconds).
horizon_end
The forecast ends here (UTC epoch seconds); the window does not restart with your request.
row.p_crash_60m
Crash odds for the current row.
row.confidence
Historical evidence; an ordinal presentation label, not a statistical confidence interval.
Responses carry as_of, issued_at, expires_at, horizon_end (UTC epoch seconds), model hashes, coverage, a historical calibration band and the current row. The forecast horizon does not restart when you request it. Band observations describe historical groups, not a confidence interval for one token.
GET
/v1/risk/{mint}/last
$0.002 USDC
Opt-in last-known odds, at most 30 minutes old
Parameters and filters
Parameter
Details
mint
Token mint.
Key response fields
as_of
Completed one-minute bars up to this time (UTC epoch seconds).
issued_at
Snapshot issue time (UTC epoch seconds).
expires_at
Fresh expiry (UTC epoch seconds).
horizon_end
The forecast ends here (UTC epoch seconds); the window does not restart with your request.
row.p_crash_60m
Crash odds for the current row.
row.confidence
Historical evidence; an ordinal presentation label, not a statistical confidence interval.
stale
Whether the stored answer is stale.
age_s
Elapsed seconds since issued_at.
horizon_remaining_s
max(0, horizon_end - now)
Last-known odds: explicit opt-in
GET /v1/risk/{mint}/last sells the covered SOL row in the latest stored snapshot
only when now - issued_at ≤ 1800 seconds. Exactly 1800 seconds is allowed; older data returns free HTTP 410
with error: "Last known odds too old", age_s and as_of.
No stored snapshot returns 503. Unknown or experimental non-SOL tokens return free 404, with available experimental information.
Last-known odds are never sold as fresh. The response explicitly includes stale,
freshness: "live" | "stale", age_s and
horizon_remaining_s = max(0, horizon_end - now). Its horizon_end remains as_of + 3600;
expires_at remains the original snapshot's fresh expiry, even when already past. This is an old forecast, not a new prediction.
When stale, confidence is downgraded one level: high → medium, medium → low, and low stays low.
Its reasons add stale data: N min old, where N is the elapsed whole minutes.
Experimental confidence is unchanged; experimental rows are never paid answers. Missing legacy confidence stays missing.
The probability, historical evidence and underlying model do not change.
The route also works while the feed is live. In that case the odds equal the fresh route's odds,
stale is false and confidence is unchanged. The price is still lower: choosing this cheaper route means explicitly accepting
its last-known semantics on every request. There is no /v1/board/last.
A fresh risk route's free 503 may include a hint and last_known_age_s when this alternative is eligible;
the hint is not permission to pay or an automatic redirect.
One current snapshot, no pagination or cursors. limit=10..500 (default 50),
sort=safest|riskiest|liquidity|newest|active (default safest).
safest — lowest predicted odds first (a ranking, not a safety claim). Ties use mint ascending.
Filters: max_risk/min_risk (0–1), min_liquidity_sol,
min_age_min/max_age_min, min_trades_5 (nonnegative integer),
min_confidence=high|medium|low. Numeric filters exclude null values; confidence filters exclude missing confidence.
Liquidity means the recorded quote-side SOL reserve, not an executable depth guarantee.
Price is $0.005 × delivered coins: 37 matches with limit 100 costs $0.185; 500 cost $2.50.
Zero matches return free HTTP 200 with empty rows and no payment headers. The paid retry returns exactly the priced count
from the current fresh ranking; rows may change. Fewer matches return free 409 matches changed; request again;
stale data returns free 503. The normalized query and count must match the requirement, and the server rechecks before settlement.
Payment and failure behavior
Send an unpaid request
Read the 402 challengePAYMENT-REQUIRED
Sign locallyPin the network, USDC asset, recipient and maximum total.
Retry with the signed paymentPAYMENT-SIGNATURE → 200 + PAYMENT-RESPONSE
x402 v2 uses PAYMENT-REQUIRED, PAYMENT-SIGNATURE and PAYMENT-RESPONSE. Read /v1/meta and the current challenge for accepted payment networks, recipients and native USDC assets. When enabled, Solana and Base are alternative ways to pay the same price for the same covered SOL-token answer. Payment chain never expands model coverage. Solana devnet and Base Sepolia use test funds; they are not mainnet.
A connection failure after settlement may leave the answer undelivered. Keep the transaction signature and reconcile before paying again. Never share a wallet seed phrase with this service.
Request limit: 60 requests per minute per IP by default, including unpaid probes. Do not cache last-known odds as current odds.
Status codes
Code
Meaning
Charged?
400
400: unknown or invalid board parameters.
No settlement.
402
402: an eligible covered answer requires payment, or payment failed. Inspect PAYMENT-RESPONSE before retrying.
Inspect PAYMENT-RESPONSE before retrying.
404
404: unknown, uncovered or experimental non-SOL mint. No settlement. Empty boards return free 200.
No settlement.
409
409: board matches/offer changed, or this signed payment was already claimed. No new settlement. For a replay, reconcile its original transaction before signing again.
No new settlement.
410
410: last-known odds exceed the 30-minute limit. No settlement.
No settlement.
422
422: malformed route input.
No settlement.
429
429: rate limited; respect Retry-After. No settlement.
No settlement.
503
503: stale/down feed on fresh-only routes, no stored snapshot, beta disabled, or service unavailable. No new settlement for an unavailable answer.
No new settlement for an unavailable answer.
How we charge
The normal risk and board routes remain fresh or free: only fresh, covered SOL answers settle. The separate opt-in last-known route may charge for a clearly labelled stored SOL answer no older than 30 minutes. Each route checks its age and coverage limits before payment work and again before settlement. Unknown, uncovered and experimental non-SOL answers are free refusals. Filters that return no rows are also free.
Risk and last-known have fixed per-answer prices; a board costs $0.005 per delivered coin, charged as one exact total. No subscription. Read current prices in /v1/meta and approve the exact x402 requirement. An already delivered signature is rejected with 409. A reconciled undelivered payment has one explicit redeem as described below. A lost connection after settlement can leave an answer undelivered: reconcile the receipt before signing again.
Redeem an undelivered answer
If an authorized call fails, keep its original PAYMENT-SIGNATURE private and check your wallet before signing another payment. The server checks uncertain settlements on-chain in the background. A receipt saying success: false with no transaction usually means nothing was charged; if your wallet shows payment, try redemption after about two minutes. Confirmation can take longer.
The Python SDK keeps the recovery credential in HodlOddsError.payment, excluded from its printed and JSON receipt fields. Explicitly call client.redeem(payment). The CLI saves an ambiguous attempt to a private 0600 file under ~/.config/hodlodds/pending/ and prints its path; run hodlodds redeem <file>. Neither automatically retries or signs again. Never log, upload or share that file or the signed header.
A manual redeem resends the identical header to the same route; boards require the same normalized query and original priced count. Add HodlOdds-Redeem: 1 to require recovery only, so an unknown payment cannot initiate settlement. Pending verification returns free 409 with Retry-After. A final unpaid result returns free 409 saying “this payment never settled; request a new offer”.
When a payment is confirmed on-chain and was not delivered, it can be redeemed once within 24 hours of its original verification. The response is the current eligible answer and includes HodlOdds-Redeemed: <transaction>, with no second settlement. Current route freshness and coverage rules still apply. A stale/uncovered answer or board with fewer matches than the original priced count is refused free and leaves the redeem available until expiry. Already redeemed or expired payments return 409. A lost redeem response cannot be delivered again.