{"openapi":"3.1.0","info":{"title":"CryptoScope API","description":"Developer-first API that scores on-chain wallet risk with explainable heuristics.","contact":{"name":"CryptoScope Team","url":"https://example.com/cryptoscope","email":"support@example.com"},"license":{"name":"Apache-2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"},"version":"0.1.0"},"servers":[{"url":"https://api.cryptoscope.local","description":"Local Dev"},{"url":"https://api.cryptoscope.example","description":"Production"}],"paths":{"/wallet/analyze":{"post":{"tags":["wallet"],"summary":"Analyze a single wallet","description":"Computes (or refreshes) risk analysis for a wallet. Returns 201 if first-time, 200 if updated.","operationId":"post_analyze_wallet_analyze_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeRequest"}}},"required":true},"responses":{"200":{"description":"Existing analysis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskAnalysisResponse"}}}},"201":{"description":"Created"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/wallet/history/recent":{"get":{"tags":["wallet"],"summary":"Recent global demo history (max 5)","description":"Returns up to the 5 most recent demo risk snapshots across any wallets (in-memory only).","operationId":"get_recent_history_wallet_history_recent_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/wallet/{address}/risk":{"get":{"tags":["wallet"],"summary":"Get latest wallet risk","description":"Fetch the most recently analyzed risk snapshot for a wallet.","operationId":"get_risk_wallet__address__risk_get","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"chain","in":"query","required":true,"schema":{"type":"string","title":"Chain"}}],"responses":{"200":{"description":"Risk snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskAnalysisResponse"}}}},"404":{"description":"Not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/wallet/analyze/batch":{"post":{"tags":["wallet"],"summary":"Analyze multiple wallets (batch)","description":"Runs risk analysis for up to 100 wallet addresses in a single request (mock mode fast).","operationId":"analyze_batch_wallet_analyze_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAnalyzeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AnalyzeResult"},"type":"array","title":"Response Analyze Batch Wallet Analyze Batch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/wallet/{address}/risk/history":{"get":{"tags":["wallet"],"summary":"List historical risk scores","description":"Returns most recent to oldest risk score snapshots with simple cursor pagination via `next_before`.","operationId":"get_history_wallet__address__risk_history_get","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"chain","in":"query","required":true,"schema":{"const":"ethereum","type":"string","title":"Chain"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Exclusive upper bound on computed_at","title":"Before"},"description":"Exclusive upper bound on computed_at"},{"name":"score_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score Min"}},{"name":"score_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score Max"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Date From"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/wallet/{address}/risk/summary":{"get":{"tags":["wallet"],"summary":"Aggregate score summary","description":"Returns count, min/max, average and first/last seen timestamps for the wallet history.","operationId":"get_summary_wallet__address__risk_summary_get","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"chain","in":"query","required":true,"schema":{"const":"ethereum","type":"string","title":"Chain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskSummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/metrics":{"get":{"summary":"Metrics Endpoint","operationId":"metrics_endpoint_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/healthz":{"get":{"summary":"Healthz","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/readyz":{"get":{"summary":"Readyz","operationId":"readyz_readyz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/analyze":{"post":{"tags":["wallet"],"summary":"V1 Post Analyze","operationId":"v1_post_analyze_v1_analyze_post","parameters":[{"name":"Accept-Version","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept-Version"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/risk":{"get":{"tags":["wallet"],"summary":"V1 Get Risk","operationId":"v1_get_risk_v1_risk_get","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string","title":"Address"}},{"name":"chain","in":"query","required":true,"schema":{"type":"string","title":"Chain"}},{"name":"Accept-Version","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept-Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["system"],"summary":"Health Check","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Check Health Get"}}}}}}}},"components":{"schemas":{"AnalyzeRequest":{"properties":{"wallet_address":{"type":"string","title":"Wallet Address"},"chain":{"type":"string","enum":["ethereum","polygon"],"title":"Chain"}},"additionalProperties":false,"type":"object","required":["wallet_address","chain"],"title":"AnalyzeRequest"},"AnalyzeResult":{"properties":{"wallet_address":{"type":"string","title":"Wallet Address"},"chain":{"type":"string","const":"ethereum","title":"Chain"},"score":{"type":"integer","title":"Score"},"computed_at":{"type":"string","format":"date-time","title":"Computed At"},"details":{"additionalProperties":true,"type":"object","title":"Details"}},"type":"object","required":["wallet_address","chain","score","computed_at","details"],"title":"AnalyzeResult"},"BatchAnalyzeRequest":{"properties":{"wallet_addresses":{"items":{"type":"string"},"type":"array","maxItems":100,"minItems":1,"title":"Wallet Addresses"},"chain":{"type":"string","const":"ethereum","title":"Chain"}},"type":"object","required":["wallet_addresses","chain"],"title":"BatchAnalyzeRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HistoryItem":{"properties":{"wallet_address":{"type":"string","title":"Wallet Address"},"chain":{"type":"string","const":"ethereum","title":"Chain"},"score":{"type":"integer","title":"Score"},"computed_at":{"type":"string","format":"date-time","title":"Computed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"details":{"additionalProperties":true,"type":"object","title":"Details"}},"type":"object","required":["wallet_address","chain","score","computed_at","created_at","details"],"title":"HistoryItem"},"HistoryResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/HistoryItem"},"type":"array","title":"Items"},"next_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Before"}},"type":"object","required":["items"],"title":"HistoryResponse"},"RiskAnalysisResponse":{"properties":{"wallet_address":{"type":"string","title":"Wallet Address"},"chain":{"type":"string","enum":["ethereum","polygon"],"title":"Chain"},"score":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Score"},"heuristic_hits":{"items":{"$ref":"#/components/schemas/WalletHeuristicHit"},"type":"array","title":"Heuristic Hits"},"breakdown":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Breakdown"},"explanation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Explanation"},"fraud_labels":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Fraud Labels"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"computed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computed At"}},"type":"object","required":["wallet_address","chain","score"],"title":"RiskAnalysisResponse"},"RiskResponse":{"properties":{"address":{"type":"string","title":"Address"},"chain":{"type":"string","title":"Chain"},"risk_score":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Risk Score"},"signals":{"items":{"type":"string"},"type":"array","title":"Signals"},"latency_ms":{"type":"integer","minimum":0.0,"title":"Latency Ms"},"score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Score"},"explanation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Explanation"},"heuristic_hits":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Heuristic Hits"},"breakdown":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Breakdown"},"fraud_labels":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Fraud Labels"}},"additionalProperties":false,"type":"object","required":["address","chain","risk_score","latency_ms"],"title":"RiskResponse","description":"Public API v1 response contract for POST /v1/analyze and GET /v1/risk.\n\nNew investor-friendly fields:\n  - risk_score (0-100)\n  - signals (top 3 concise strings)\n  - latency_ms (server measured)\n\nLegacy mirrors are included to preserve backward compatibility with existing UIs:\n  - score\n  - explanation\n  - heuristic_hits\n  - breakdown"},"RiskSummaryResponse":{"properties":{"address":{"type":"string","title":"Address"},"chain":{"type":"string","title":"Chain"},"count":{"type":"integer","title":"Count"},"min_score":{"type":"integer","title":"Min Score"},"max_score":{"type":"integer","title":"Max Score"},"avg_score":{"type":"number","title":"Avg Score"},"first_seen_at":{"type":"string","format":"date-time","title":"First Seen At"},"last_seen_at":{"type":"string","format":"date-time","title":"Last Seen At"}},"type":"object","required":["address","chain","count","min_score","max_score","avg_score","first_seen_at","last_seen_at"],"title":"RiskSummaryResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WalletHeuristicHit":{"properties":{"code":{"type":"string","title":"Code"},"weight":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Weight"},"details":{"additionalProperties":true,"type":"object","title":"Details"}},"type":"object","required":["code","weight"],"title":"WalletHeuristicHit","description":"Public API v1 shape (stable) for heuristic hits returned by endpoints."}}}}