{"openapi":"3.1.0","info":{"title":"GRADUATE","description":"Live graduation probability + smart-money intelligence for pump.fun. Public API requires a free or paid key.","contact":{"name":"GRADUATE","url":"https://graduateoracle.fun/"},"version":"1.0.0"},"paths":{"/api/v1/live":{"get":{"tags":["v1"],"summary":"Live graduation probabilities","description":"Returns currently-tracked non-mayhem pump.fun mints with k-NN graduation probability scores. Updates every ~5 seconds.","operationId":"live_api_v1_live_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":60,"title":"Limit"}},{"name":"min_prob","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"description":"Filter to mints with at least this graduation probability.","default":0.0,"title":"Min Prob"},"description":"Filter to mints with at least this graduation probability."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/probe/{mint}":{"get":{"tags":["v1"],"summary":"Score a single mint","description":"Returns the same enriched mint payload as /api/v1/live (grad probability, k-NN context, all bot/quality/activity signals, top buyers list). Bypasses the dashboard's auto-hide filter — even mints we'd hide from the dashboard are returned, with a `hide_reason` field set so callers can decide for themselves.","operationId":"probe_api_v1_probe__mint__get","parameters":[{"name":"mint","in":"path","required":true,"schema":{"type":"string","description":"Full Solana mint address","title":"Mint"},"description":"Full Solana mint address"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/smart_money_active":{"get":{"tags":["v1"],"summary":"Live mints with smart-money wallets currently positioned","description":"Filtered view of /live: only mints where one or more leaderboard wallets (min_total≥8, smart_score≥0.30) are *currently* in the top buyers. Sorted by smart-money count (most wallets first), tie-broken by graduation probability. Useful for tail-trading proven wallets in real time.","operationId":"smart_money_active_api_v1_smart_money_active_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"min_smart","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Minimum smart-money wallet count for a mint to surface.","default":1,"title":"Min Smart"},"description":"Minimum smart-money wallet count for a mint to surface."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/runners":{"get":{"tags":["v1"],"summary":"Live mints with high runner odds from current price","description":"Filtered view of /live ranked by `runner_prob_5x_from_now` — i.e. probability the mint reaches ≥5× ITS CURRENT PRICE (not its launch price). This is the trader-relevant sort: highest expected upside if you buy at the price you see.","operationId":"runners_api_v1_runners_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"tier","in":"query","required":false,"schema":{"type":"string","pattern":"^(2x|3x|5x|10x|20x)$","description":"Which runner tier to rank by (from-now semantics).","default":"5x","title":"Tier"},"description":"Which runner tier to rank by (from-now semantics)."},{"name":"min_prob","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"description":"Minimum from-now probability for the chosen tier.","default":0.05,"title":"Min Prob"},"description":"Minimum from-now probability for the chosen tier."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signals":{"get":{"tags":["v1"],"summary":"Composite cross signal stream (cursor-paginated)","description":"The machine-consumable signal feed. Returns composite-receipts crossings (ACT / WATCH tier) in the order they became deliverable, newest-cursor last. Poll with the `cursor` from the previous response as `since` to get only new signals — zero missed crossings, zero duplicates across polls.\n\nEach signal is the same event delivered to the Telegram bot, with full feature payload. `tier` is ACT (gp_60 ≥ 0.25, ~75% historical grad rate) or WATCH (gp_60 in [0.10, 0.25), ~28%). Cursor is an opaque integer (internally the deliverability timestamp) — treat it as opaque, store it, pass it back. Recommended poll interval: 1-3s for execution use.\n\nWallet-redaction safe: aggregate counts + scalars only, no wallet addresses.","operationId":"signals_api_v1_signals_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Cursor from prior response. 0 (default) returns the last hour.","default":0,"title":"Since"},"description":"Cursor from prior response. 0 (default) returns the last hour."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"tier","in":"query","required":false,"schema":{"type":"string","pattern":"^(ACT|WATCH|SCOUT|all)$","description":"Filter by tier. 'all' = ACT + WATCH + SCOUT.","default":"all","title":"Tier"},"description":"Filter by tier. 'all' = ACT + WATCH + SCOUT."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wallet/{address}":{"get":{"tags":["v1"],"summary":"Wallet pump.fun history","description":"Returns lifetime stats for a wallet (using observed first-12-char prefix) including graduation/runner/rug counts and smart score.","operationId":"wallet_api_v1_wallet__address__get","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","description":"Full wallet address (we match by 12-char prefix)","title":"Address"},"description":"Full wallet address (we match by 12-char prefix)"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wallet/link":{"post":{"tags":["v1"],"summary":"Link a Solana wallet to your API key (proves ownership via Phantom signMessage)","description":"Proves you own a Solana wallet so we can credit its $ORACLE holdings against your tier (post-launch). The client signs the EXACT message `graduate-oracle :: link wallet to api_key_prefix=<KEY_PREFIX> :: <WALLET>` with Phantom's signMessage, then submits {wallet, signature_b58, key_prefix}. We verify the ed25519 signature against the wallet's public key, then persist the wallet on your api_key. Idempotent; re-call to relink.","operationId":"wallet_link_api_v1_wallet_link_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"},"example":{"wallet":"<your-wallet>","signature_b58":"<base58 signature>","key_prefix":"grad_…"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wallets/leaderboard":{"get":{"tags":["v1"],"summary":"Smart money / sniper leaderboard","description":"Top wallets ranked by smart_score (graduation rate − rug rate, sample-size weighted) or sniper-rug rate.","operationId":"leaderboard_api_v1_wallets_leaderboard_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","pattern":"^(smart|sniper|graduate)$","default":"smart","title":"Kind"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"min_total","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":8,"title":"Min Total"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks":{"post":{"tags":["v1"],"summary":"Register a webhook subscription (Pro tier)","description":"Register a URL we'll POST signed event payloads to. Each delivery includes an `X-Graduate-Signature` header containing HMAC-SHA256(secret, body). The `secret` field is returned ONCE on creation — store it; we don't expose it on subsequent reads. Use `events=\"*\"` to subscribe to every event kind, or a comma-separated list (e.g. `runner_dev,smart_money_in`).","operationId":"webhooks_register_api_v1_webhooks_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"},"example":{"url":"https://your.app/hook","events":"*"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1"],"summary":"List your webhook subscriptions","operationId":"webhooks_list_api_v1_webhooks_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/{webhook_id}":{"delete":{"tags":["v1"],"summary":"Deactivate a webhook subscription","operationId":"webhooks_delete_api_v1_webhooks__webhook_id__delete","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"integer","minimum":1,"title":"Webhook Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/deliveries":{"get":{"tags":["v1"],"summary":"Recent delivery attempts (debugging)","description":"Last N delivery attempts across all your webhooks, including status code and any error.","operationId":"webhooks_deliveries_api_v1_webhooks_deliveries_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/composite_predictions":{"get":{"tags":["v1"],"summary":"Composite-signal predictions log","description":"Returns rows from the composite_predictions table — every time the hot-launch composite signal (smart_money_in × max_mult × freshness) crossed the rolling-24h P90 threshold AND market cap was above the $5,000 floor, dedupe-by-mint first-cross. Outcome columns (did_graduate, peak_mult_24h, did_sustain_30m) are NULL until 24h post-cross, then populated by the background resolver from existing outcome tables. Paired with /api/v1/composite_ledger for tamper-evident merkle root verification.","operationId":"composite_predictions_list_api_v1_composite_predictions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"only_resolved","in":"query","required":false,"schema":{"type":"boolean","description":"If true, return only crosses with outcomes resolved.","default":false,"title":"Only Resolved"},"description":"If true, return only crosses with outcomes resolved."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/composite_ledger":{"get":{"tags":["v1"],"summary":"Composite predictions merkle commits","description":"Returns hourly merkle root commits over composite_predictions rows. Same tamper-evident discipline as /api/ledger/commits (grad_prob track), applied to the composite track. Leaves use a composite-specific format starting at version 1.","operationId":"composite_ledger_commits_api_v1_composite_ledger_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stats":{"get":{"tags":["v1"],"summary":"Platform-wide aggregate stats","operationId":"stats_api_v1_stats_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live":{"get":{"summary":"Api Live","description":"Hot path. Reads entirely from the precomputed score cache — no\nsnapshot file I/O, no scoring loop, no DB writes. Bootstrap path\n(cache empty at boot) falls back to a one-time inline read+compute.\n\n2026-06-09: serves pre-serialized JSON bytes from the precompute\ncache — eliminates per-request dict→JSON cost (~400 KB serialization\nwas happening on every hit, multiplied by every client polling).\nCache-Control header lets Fly's edge proxy hold the response for 2s,\nfurther dropping load when multiple clients are polling concurrently.","operationId":"api_live_api_live_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/wallets":{"get":{"summary":"Api Wallets","operationId":"api_wallets_api_wallets_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"smart","title":"Kind"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"min_total","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Min Total"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/paper":{"get":{"tags":["paper"],"summary":"Paper-trading P&L","description":"Live performance of the paper-trading harness running three thresholds\n(70/80/90% grad probability). No auth — public proof-of-signal.","operationId":"api_paper_api_paper_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/postmortems":{"get":{"tags":["paper"],"summary":"Closed trades with catastrophic loss + full entry context","description":"Returns paper trades that closed with a loss ≥ `min_loss_pct` (default\n−30%), most-recent first, including the full enriched-mint snapshot we\nhad at entry time.\n\nDefault surfaces only rows that have entry_context_json populated (i.e.\ntrades opened after 2026-04-28 when the column was added). Pass\n`require_context=false` to include older context-less rows.\n\nUseful for:\n- Understanding which mints fooled all our filters at entry\n- Aggregating which bot_flags fired (or didn't) on losing trades\n- Driving future entry-filter improvements based on real failures\n\nNo auth — full transparency.","operationId":"api_postmortems_api_postmortems_get","parameters":[{"name":"min_loss_pct","in":"query","required":false,"schema":{"type":"number","default":0.3,"title":"Min Loss Pct"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"require_context","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Require Context"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/accuracy":{"get":{"tags":["calibration"],"summary":"Model calibration · proven accuracy","description":"Two-tier proof of the oracle's accuracy.\n\n`lifetime` — leave-one-out k-NN cross-validation on the full historical\ncurve index. Every sampled mint is predicted using all OTHER mints as\nneighbors (never itself). Recomputed every 6h.\n\n`forward` — every live prediction we've made since launch, joined against\nactual graduation outcomes once each mint resolves. Bulletproof: every\nprediction was recorded BEFORE we knew the outcome.\n\nFor new deployments `forward` will have few resolved samples; lifetime\ncarries the marketing weight until forward catches up (~30 days).","operationId":"api_accuracy_api_accuracy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/scope":{"get":{"tags":["calibration"],"summary":"Product scope · what we predict and at what age","description":"Documents what predictions we make, the age window we make them at,\nthe corpus they're calibrated against, and what we explicitly DO NOT\nclaim. Honest scope = defensible product.","operationId":"api_scope_api_scope_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/predictor/health":{"get":{"tags":["calibration"],"summary":"Rug-prob predictor health · sample counts, status, corpus cross-check","description":"Live state of the rug_prob k-NN predictor: sample counts, warming/live\nstatus, calibration freshness, and a corpus-wide cross-check of distinct\nrugged mints across all checkpoint ages (not just the 60s training set).\n\nUse this to decide whether the predictor has graduated from \"warming\" to\n\"live\" and whether MIN_SAMPLES / MIN_POSITIVE_SAMPLES thresholds should\nmove.","operationId":"api_predictor_health_api_predictor_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/ledger/commits":{"get":{"tags":["calibration"],"summary":"Tamper-evident hourly merkle commits over predictions","description":"Returns recent hourly merkle commitments. Each commit locks in every\nprediction made during one hour — its merkle_root_hex is a function of\nthe (mint, age_bucket, predicted_prob, ...) of every covered prediction.\nSnapshot this endpoint regularly. If a past root ever changes, we\nrewrote history.","operationId":"api_ledger_commits_api_ledger_commits_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Since"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ledger/proof/{prediction_id}":{"get":{"tags":["calibration"],"summary":"Merkle proof that a prediction was committed in its hour-root","description":"Given a prediction id, returns its leaf hash, the merkle path of\nsibling hashes from leaf to root, and the committed root for that hour.\nVerify locally: hash the leaf payload, walk the path applying\nsha256(left || right) at each step, confirm the result equals\nmerkle_root_hex of the commit.","operationId":"api_ledger_proof_api_ledger_proof__prediction_id__get","parameters":[{"name":"prediction_id","in":"path","required":true,"schema":{"type":"integer","title":"Prediction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/alerts/audit":{"get":{"tags":["calibration"],"summary":"Recent TG alert fires joined with the actual outcome of each called mint","description":"For each TG alert we fired in the last `hours`, return the call details\n(kind, threshold, predicted_prob at fire time) and the actual outcome\n(max_mult achieved, did_graduate, resolved_at). The receipt for \"did\nyour alerts actually catch winners?\" — readable by anyone.\n\nFiltered to the currently-active grad_prob rule and fires logged at or\nafter that rule's activation. Without this floor, fires from older rules\n(different thresholds, different criteria) leak in and contaminate the\naggregate hit rates with traffic that no longer represents the product.","operationId":"api_alerts_audit_api_alerts_audit_get","parameters":[{"name":"hours","in":"query","required":false,"schema":{"type":"integer","default":24,"title":"Hours"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gate_validation":{"get":{"tags":["calibration"],"summary":"Pre-registered sustains-gate criterion · mechanical execution","description":"Returns the most recent gate-validation run (set `history` for more).\nThe criterion is pre-registered in BACKLOG.md ('Sustains-gate validation\ncriterion'); this endpoint executes it mechanically against the live\ndata on an hourly tick. The decision field is one of:\n\n- \"warming\"   — n < 15 in either bucket; not enough data yet\n- \"fails\"     — ratio < 1.5×; sustains doesn't discriminate, gate stays display-only\n- \"hold\"      — 1.5× ≤ ratio < 2×; collect 30 more fires before deciding\n- \"validates\" — ratio ≥ 2× AND n ≥ 15 each; gate ships as a hard suppression\n\nTwo side stratifications are computed alongside the primary criterion:\nby `manufactured_pump` and by `bundle_detected`. These were flagged\n2026-05-04 as label-leak hypotheses — if 100% of post-bond runners are\nbundled/manufactured, the model has effectively learned \"bundled scam =\nrunner\" rather than a real signal. Same population, different bucketing.\nNo decision rule applied to the side analyses; they're observational.","operationId":"api_gate_validation_api_gate_validation_get","parameters":[{"name":"history","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"History"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/predictions/by_mint/{mint}":{"get":{"tags":["calibration"],"summary":"What we predicted on a specific mint, at the moment we predicted it","description":"Look up our forward-logged predictions for a single mint. Returns\nevery (age_bucket × predicted_prob) row we logged + the resolved outcome\nif available. This is the receipt for \"what did you say about THIS\ncoin?\" — every prediction is timestamped and locked in via the merkle\nledger before the outcome was known.","operationId":"api_predictions_by_mint_api_predictions_by_mint__mint__get","parameters":[{"name":"mint","in":"path","required":true,"schema":{"type":"string","title":"Mint"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wallet/{short}":{"get":{"summary":"Api Wallet Lookup","description":"Lookup by 12-char short prefix — used internally by the bot to avoid\nloading its own copy of the wallet index. Public, no auth needed.","operationId":"api_wallet_lookup_api_wallet__short__get","parameters":[{"name":"short","in":"path","required":true,"schema":{"type":"string","title":"Short"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/verify/{wallet}":{"get":{"tags":["calibration"],"summary":"Public wallet verification (redacted-for-public)","description":"Public read-only verification of a single, named Solana wallet.\n\nReturns observed on-chain stats: graduation/runner/rug counts, fast-snipe\nrate, total invested. DELIBERATELY OMITS smart_score, rank, percentile,\nand any cross-wallet comparison — those would leak the discovery moat\n(see project_receipts_reputation_layer_strategy memory). Public verifies\nnamed wallets; private B2B discovers unknown wallets. Same engine,\nsurgically separate exposure.","operationId":"api_verify_wallet_api_verify__wallet__get","parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string","title":"Wallet"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/health":{"get":{"tags":["status"],"summary":"Public system health (latest watchdog tick + active alerts)","description":"Machine-readable system-health snapshot for terminals embedding us.\n\nReturns the latest watchdog tick (disk / memory / resolver-stuck count)\nplus any currently-active alerts. Designed to be polled by external\nuptime monitors (UptimeRobot, BetterStack, etc.) and by terminals'\nintegration health checks. Public, no auth — being transparent about\nuptime IS the trust signal.","operationId":"api_health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/burn/pending":{"get":{"tags":["token"],"summary":"Pending ORACLE burns (public transparency)","description":"Pending ORACLE burn queue — both pay-with-token receipts and weekly\nrevenue commitments. Public-readable: every burn the protocol owes,\nvisible before execution. The receipts brand applied to token mechanics.","operationId":"api_burn_pending_api_burn_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/burn/history":{"get":{"tags":["token"],"summary":"Executed ORACLE burns (public history)","description":"History of executed ORACLE burns with on-chain tx signatures —\npay-with-token receipts and weekly revenue buy+burns. Public-readable:\nevery burn happened, with the tx anyone can verify.","operationId":"api_burn_history_api_burn_history_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/verdict":{"get":{"tags":["calibration"],"summary":"Locked pre-registered verdict snapshot (public, machine-readable)","description":"Machine-readable snapshot of the 2026-06-02 Branch A verdict on the\n3-tier composite signal — for terminals embedding our 'verified' badge.\n\nPublic (no auth) by design: this is the receipts-moat payload anyone\nintegrating us would want to display next to the signal. Pulled from\nthe immutable prereg_verdicts row on /data so the response is exactly\nwhat was ratified, not a re-computation.","operationId":"api_verdict_api_verdict_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/status":{"get":{"tags":["status"],"summary":"System status JSON","description":"Live system health: uptime, recent /api/live latency, daemon\nheartbeats. Polled every 10s by /status. No auth — public artifact.","operationId":"api_status_api_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/sol_price":{"get":{"tags":["status"],"summary":"Live SOL/USD price (5-min cached)","description":"Cached Jupiter SOL→USD quote, used by the marketing page to render\ndollar-equivalent prices that don't go stale when SOL moves. Refreshes\nserver-side every 5 minutes; clients can poll freely.","operationId":"api_sol_price_api_sol_price_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/upgrade":{"post":{"tags":["payments"],"summary":"Create a SOL payment intent","description":"One-shot signup. If no existing API key is supplied, this endpoint will\nissue a fresh one and link the payment intent to it — no two-step \"get\nfree key, then upgrade\" flow needed.\n\nBody: {\n  \"tier\": \"pro\",                           // default \"pro\"\n  \"plan\": \"monthly\" | \"yearly\",            // default \"monthly\"\n  \"key\": \"<existing api key>\",             // optional · upgrades that key\n  \"email\": \"you@example.com\",              // optional · for renewal reminders\n  \"telegram_id\": <int>                     // optional · binds to a TG user\n}\n\nReturns memo + amount + Phantom deeplinks AND (if a new key was minted)\nthe plaintext key shown ONCE. Send SOL with the memo to auto-activate.","operationId":"create_upgrade_intent_api_upgrade_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Payload"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/upgrade/{memo}":{"get":{"tags":["payments"],"summary":"Check intent status","operationId":"check_intent_api_upgrade__memo__get","parameters":[{"name":"memo","in":"path","required":true,"schema":{"type":"string","title":"Memo"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/keys/new":{"post":{"tags":["keys"],"summary":"Issue a free API key","description":"Body (all optional): { \"email\": \"you@example.com\", \"label\": \"my-bot\" }\n\nReturns the plaintext key ONCE — store it, we don't keep a copy.\n\nEmail is optional. Skipping it gives you a fully anonymous key; the\nonly downside is that we can't email you renewal reminders or recover\na lost key. IP-based rate limit (5/hr) prevents abuse.","operationId":"issue_free_key_api_keys_new_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/me":{"get":{"tags":["keys"],"summary":"Inspect your current API key","operationId":"me_api_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Index","operationId":"index__get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}