{"openapi":"3.1.0","info":{"title":"LPSignal API","version":"1.0.0","description":"Concentrated-liquidity LP opportunities ranked by net APR (fees − impermanent loss) of specific price ranges, from hourly backtests on exact on-chain fees; signals, a scored track record, risk alerts and a smart-LP leaderboard.\n\nAll APR-like numbers are fractions per year (0.42 = 42%), backtested history, not a forecast.\n\nReads work without a key (the free view: opportunity signals 24 h late, the smart-LP top 10 masked). An API key (Settings on lpsignal.app) is sent as `Authorization: Bearer lps_…`.\n\nLive push: WebSocket `wss://api.lpsignal.app/v1/stream?key=…` and signed webhooks (see the docs). AI agents: the MCP server at `/v1/mcp` (sign in with OAuth 2.1, or an API key) and `/v1/mcp/public` (the free view, no sign-in).\n\nErrors are JSON `{ \"error\": \"<code>\", … }`: 400 validation, 401 auth, 403 plan, 404, 429 rate limit (Retry-After).","contact":{"email":"support@lpsignal.app","url":"https://lpsignal.app/docs"}},"externalDocs":{"url":"https://lpsignal.app/docs","description":"Documentation, SDKs (npm/PyPI: lpsignal), WebSocket and webhooks"},"servers":[{"url":"https://api.lpsignal.app"}],"security":[{},{"apiKey":[]}],"tags":[{"name":"pools"},{"name":"signals"},{"name":"smart LPs"},{"name":"account"},{"name":"agents"},{"name":"meta"}],"paths":{"/v1/health":{"get":{"tags":["meta"],"operationId":"health","summary":"Liveness","security":[{}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}}}}},"/v1/chains":{"get":{"tags":["meta"],"operationId":"listChains","summary":"Covered chains, how far each is scanned, active pools","security":[{}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"chains":{"type":"array","items":{"type":"object","properties":{"chain":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]},"block":{"type":"string"},"blockTs":{"type":"string"},"firstBlockTs":{"type":"string"},"lagSec":{"type":"integer"},"activePools":{"type":"integer"}}}}}}}}}}}},"/v1/openapi.json":{"get":{"tags":["meta"],"operationId":"openapi","summary":"This document","security":[{}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/pools":{"get":{"tags":["pools"],"operationId":"listPools","summary":"Pools ranked by their best range's net APR","security":[{}],"parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]}},{"name":"class","in":"query","required":false,"schema":{"type":"string","enum":["stable","correlated","volatile"]}},{"name":"window","in":"query","required":false,"schema":{"type":"integer","enum":[1,24,168,720]},"description":"backtest window in hours (default 168)"},{"name":"minTvlUsd","in":"query","required":false,"schema":{"type":"number"},"description":"default 10000"},{"name":"minPoolApr","in":"query","required":false,"schema":{"type":"number"},"description":"pool-level 24h fee APR at least this (fraction)"},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["netApr","feeApr","ilApr","inRange","emissionApr","tvl","fee","volume24h","fees24h","poolApr"]}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"pools":{"type":"array","items":{"$ref":"#/components/schemas/PoolListItem"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"sort":{"type":"string"},"order":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/E400"}}}},"/v1/pools/{chain}/{address}":{"get":{"tags":["pools"],"operationId":"getPool","summary":"A pool and the backtest of every range it is evaluated on (1 h, 24 h, 7 d, 30 d)","security":[{}],"parameters":[{"name":"chain","in":"path","required":true,"schema":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]}},{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$","description":"pool address, or a Uniswap v4 pool id"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"pool":{"type":"object","description":"the pool record (tokens, fee, tick spacing, TVL, …)"},"metrics":{"type":"array","items":{"type":"object","properties":{"windowHours":{"type":"integer"},"rangeBp":{"type":"integer","description":"half-width of the range in basis points of price; 0 = full range"},"tickLower":{"type":"integer"},"tickUpper":{"type":"integer"},"exact":{"type":"boolean","description":"every hour has exact (feeGrowth) fees; only exact figures fire signals"},"feeApr":{"type":"number","description":"fees earned, annualised (a fraction: 0.42 = 42%)"},"ilApr":{"type":"number","description":"impermanent loss vs holding, annualised (≤ 0) (a fraction: 0.42 = 42%)"},"netApr":{"type":"number","description":"feeApr + ilApr (a fraction: 0.42 = 42%)"},"inRangeRatio":{"type":"number","description":"share of the window the price spent in the range (a fraction: 0.42 = 42%)"},"asOf":{"type":"string","format":"date-time"}}}}}}}}},"400":{"$ref":"#/components/responses/E400"},"404":{"$ref":"#/components/responses/E404"}}}},"/v1/pools/{chain}/{address}/hours":{"get":{"tags":["pools"],"operationId":"getPoolHours","summary":"Hourly aggregates (swaps, volume, fees per unit of liquidity, ticks)","security":[{}],"parameters":[{"name":"chain","in":"path","required":true,"schema":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]}},{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$","description":"pool address, or a Uniswap v4 pool id"}},{"name":"hours","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":720},"description":"default 168"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"hours":{"type":"array","items":{"type":"object"}}}}}}},"400":{"$ref":"#/components/responses/E400"},"404":{"$ref":"#/components/responses/E404"}}}},"/v1/pools/{chain}/{address}/backtest":{"get":{"tags":["pools"],"operationId":"backtestRange","summary":"Backtest a ±rangePct% range (0 = full range) over the last N days","security":[{}],"description":"Rate limited separately (30 a minute per key or IP).","parameters":[{"name":"chain","in":"path","required":true,"schema":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]}},{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$","description":"pool address, or a Uniswap v4 pool id"}},{"name":"rangePct","in":"query","required":true,"schema":{"type":"number","minimum":0,"maximum":50},"description":"0 = full range, else ≥ 0.01"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":30},"description":"default 7"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"windowHours":{"type":"integer"},"rangeBp":{"type":"integer","description":"half-width of the range in basis points of price; 0 = full range"},"tickLower":{"type":"integer"},"tickUpper":{"type":"integer"},"exact":{"type":"boolean","description":"every hour has exact (feeGrowth) fees; only exact figures fire signals"},"feeApr":{"type":"number","description":"fees earned, annualised (a fraction: 0.42 = 42%)"},"ilApr":{"type":"number","description":"impermanent loss vs holding, annualised (≤ 0) (a fraction: 0.42 = 42%)"},"netApr":{"type":"number","description":"feeApr + ilApr (a fraction: 0.42 = 42%)"},"inRangeRatio":{"type":"number","description":"share of the window the price spent in the range (a fraction: 0.42 = 42%)"},"asOf":{"type":"string","format":"date-time"},"chain":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]},"address":{"type":"string"},"days":{"type":"integer"},"startTick":{"type":"integer"},"endTick":{"type":"integer"},"uncertainFeeApr":{"type":"number","description":"fees of hours straddling a range edge (a fraction: 0.42 = 42%)"},"feesExact":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/E400"},"404":{"$ref":"#/components/responses/E404"},"429":{"$ref":"#/components/responses/E429"}}}},"/v1/signals":{"get":{"tags":["signals"],"operationId":"listSignals","summary":"Signals, newest first (what the caller may see)","description":"Risk alerts are live for everyone; opportunities (net_apr, burst, hot_pool) live with a paid key, else 24 h after they fire; smart_lp with Pro. Page newest-first with `before` (the `next` id), or by `offset` (with `total`) when sorting by return/outcome.","parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["net_apr","burst","hot_pool","tvl_outflow","depeg","smart_lp"]}},{"name":"kinds","in":"query","required":false,"schema":{"type":"string"},"description":"comma-separated kinds"},{"name":"source","in":"query","required":false,"schema":{"type":"string","enum":["default","rules","subscribed"]},"description":"default = global signals; rules = your custom-rule matches; subscribed = what your push channels deliver"},{"name":"before","in":"query","required":false,"schema":{"type":"string"},"description":"signal id: older than this"},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["time","return","outcome"]}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"signals":{"type":"array","items":{"$ref":"#/components/schemas/Signal"}},"next":{"oneOf":[{"type":"string"},{"type":"null"}]},"total":{"type":"integer"}}}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"}}}},"/v1/signals/stats":{"get":{"tags":["signals"],"operationId":"signalStats","summary":"Track record: how past signals really did (re-backtested on their exact ticks)","security":[{}],"parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["net_apr","burst"]},"description":"default net_apr"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":7,"maximum":365},"description":"default 30"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"integer"},"kind":{"type":"string"},"scored":{"type":"integer"},"inexact":{"type":"integer"},"positive":{"type":"integer"},"medianRealizedNetApr":{"oneOf":[{"type":"number"},{"type":"null"}]},"medianSignalNetApr":{"oneOf":[{"type":"number"},{"type":"null"}]},"worst":{"oneOf":[{"type":"object"},{"type":"null"}]},"points":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"signalNetApr":{"type":"number"},"realizedNetApr":{"type":"number"}}}}}}}}},"400":{"$ref":"#/components/responses/E400"}}}},"/v1/signals/{id}":{"get":{"tags":["signals"],"operationId":"getSignal","summary":"One signal","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Signal"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"404":{"$ref":"#/components/responses/E404"}}}},"/v1/smart-lps":{"get":{"tags":["smart LPs"],"operationId":"smartLpLeaderboard","summary":"Wallets ranked by LP profit vs holding (non-Pro: top 10, masked)","parameters":[{"name":"windowDays","in":"query","required":false,"schema":{"type":"integer","enum":[30,90]}},{"name":"chain","in":"query","required":false,"schema":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"windowDays":{"type":"integer"},"full":{"type":"boolean"},"wallets":{"type":"array","items":{"type":"object"}},"total":{"type":"integer"}}}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"}}}},"/v1/smart-lps/{owner}/positions":{"get":{"tags":["smart LPs"],"operationId":"smartLpPositions","summary":"A wallet's open and closed positions (Pro); the two lists page separately","security":[{"apiKey":[]}],"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100},"description":"per list (default 50)"},{"name":"openOffset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000}},{"name":"openSort","in":"query","required":false,"schema":{"type":"string","enum":["lastEvent","openedAt","entryUsd"]}},{"name":"openOrder","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"closedOffset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000}},{"name":"closedSort","in":"query","required":false,"schema":{"type":"string","enum":["closedAt","openedAt","capitalUsd","pnlUsd"]}},{"name":"closedOrder","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"}}}},"/v1/me":{"get":{"tags":["account"],"operationId":"getMe","summary":"The key's account: plan, channels, subscriptions","security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/E401"}}}},"/v1/me/api-key":{"post":{"tags":["account"],"operationId":"createApiKey","summary":"Create or replace the API key (shown once)","security":[{"apiKey":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"replace":{"type":"boolean","description":"false = only if there is none (409 otherwise); default true"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/E401"},"409":{"$ref":"#/components/responses/E409"}}}},"/v1/me/webhook":{"put":{"tags":["account"],"operationId":"setWebhook","summary":"Set the webhook URL (https, public); the signing secret is returned once","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"secret":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"}}},"delete":{"tags":["account"],"operationId":"deleteWebhook","summary":"Remove the webhook","security":[{"apiKey":[]}],"responses":{"204":{"description":"removed"},"401":{"$ref":"#/components/responses/E401"}}}},"/v1/me/subscriptions":{"put":{"tags":["account"],"operationId":"setSubscriptions","summary":"The signal kinds pushed to this account (Telegram, webhook, WebSocket without ?kinds)","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kinds"],"properties":{"kinds":{"type":"array","items":{"type":"string","enum":["net_apr","burst","hot_pool","tvl_outflow","depeg","smart_lp"]}}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"subscriptions":{"type":"array","items":{"type":"string"}}}}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"}}}},"/v1/me/telegram-link":{"post":{"tags":["account"],"operationId":"telegramLink","summary":"A one-time code to send to the Telegram bot as /start <code>","security":[{"apiKey":[]}],"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"instruction":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/E401"}}}},"/v1/me/rules":{"get":{"tags":["account"],"operationId":"listRules","summary":"Custom alert rules, the plan's limit and today's matches","security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/Rule"}},"limit":{"type":"integer"},"dailyCap":{"type":"integer"},"matchesToday":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/E401"}}},"post":{"tags":["account"],"operationId":"createRule","summary":"Create a rule (paid plans: Basic 3, Pro 20)","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleInput"}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Rule"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"}}}},"/v1/me/rules/{id}":{"put":{"tags":["account"],"operationId":"updateRule","summary":"Replace a rule","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Rule"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"404":{"$ref":"#/components/responses/E404"}}},"delete":{"tags":["account"],"operationId":"deleteRule","summary":"Delete a rule","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"deleted"},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"404":{"$ref":"#/components/responses/E404"}}}},"/v1/me/follows":{"get":{"tags":["smart LPs"],"operationId":"listFollows","summary":"Followed wallets (Pro)","security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"follows":{"type":"array","items":{"type":"object","properties":{"owner":{"type":"string"},"since":{"type":"string"}}}}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"}}}},"/v1/me/follows/{owner}":{"put":{"tags":["smart LPs"],"operationId":"follow","summary":"Follow a wallet (Pro, up to 50): its new positions become smart_lp signals","security":[{"apiKey":[]}],"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"owner":{"type":"string"},"following":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"}}},"delete":{"tags":["smart LPs"],"operationId":"unfollow","summary":"Stop following a wallet","security":[{"apiKey":[]}],"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"responses":{"204":{"description":"removed"},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"}}}},"/v1/mcp":{"get":{"tags":["agents"],"operationId":"mcpGet","summary":"Not used (405): the MCP server answers POSTs only","security":[{}],"responses":{"405":{"description":"POST only"}}},"post":{"tags":["agents"],"operationId":"mcp","summary":"MCP server for AI agents, as your account (OAuth sign-in or API key)","security":[{"apiKey":[]}],"description":"Model Context Protocol (Streamable HTTP, stateless JSON-RPC): initialize, tools/list, tools/call. Read-only tools: list_pools, find_pair_pools, get_pool, backtest_range, list_signals, signal_track_record, smart_lp_leaderboard, my_account. Needs an OAuth 2.1 access token (discovery: /.well-known/oauth-protected-resource/v1/mcp) or an API key; without one: 401 with WWW-Authenticate.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"one JSON-RPC 2.0 message per request (no batches)"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"a JSON-RPC 2.0 response"}}}},"202":{"description":"notification accepted"},"401":{"description":"sign in: WWW-Authenticate names the protected resource metadata"}}}},"/v1/mcp/public":{"get":{"tags":["agents"],"operationId":"mcpPublicGet","summary":"Not used (405): POST only","security":[{}],"responses":{"405":{"description":"POST only"}}},"post":{"tags":["agents"],"operationId":"mcpPublic","summary":"MCP server for AI agents, the free view without sign-in","security":[{}],"description":"The same tools as /v1/mcp except my_account, as an anonymous caller sees them (opportunity signals 24 h late, the smart-LP top 10 masked). Credentials are ignored.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"one JSON-RPC 2.0 message per request (no batches)"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"a JSON-RPC 2.0 response"}}}},"202":{"description":"notification accepted"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An LPSignal API key: `Authorization: Bearer lps_…`"}},"responses":{"E400":{"description":"invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E401":{"description":"missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E403":{"description":"the plan does not include this","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E404":{"description":"not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E409":{"description":"conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E429":{"description":"rate limited (Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"a stable code, e.g. invalid_request, invalid_api_key, pool_not_found, pro_required, rate_limited"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}},"PoolListItem":{"type":"object","properties":{"chain":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]},"address":{"type":"string"},"dex":{"type":"string"},"pair":{"type":"string"},"fee":{"type":"integer","description":"fee tier in millionths (500 = 0.05%)"},"pairClass":{"type":"string"},"tvlUsd":{"type":"number"},"tvlAt":{"oneOf":[{"type":"string"},{"type":"null"}]},"volume24hUsd":{"oneOf":[{"type":"number"},{"type":"null"}]},"fees24hUsd":{"oneOf":[{"type":"number","description":"ESTIMATED: volume × fee rate"},{"type":"null"}]},"poolApr24h":{"oneOf":[{"type":"number","description":"pool-level 24h fee APR, as DEX sites show it (a fraction: 0.42 = 42%)"},{"type":"null"}]},"best":{"type":"object","properties":{"windowHours":{"type":"integer"},"rangeBp":{"type":"integer","description":"half-width of the range in basis points of price; 0 = full range"},"tickLower":{"type":"integer"},"tickUpper":{"type":"integer"},"exact":{"type":"boolean","description":"every hour has exact (feeGrowth) fees; only exact figures fire signals"},"feeApr":{"type":"number","description":"fees earned, annualised (a fraction: 0.42 = 42%)"},"ilApr":{"type":"number","description":"impermanent loss vs holding, annualised (≤ 0) (a fraction: 0.42 = 42%)"},"netApr":{"type":"number","description":"feeApr + ilApr (a fraction: 0.42 = 42%)"},"inRangeRatio":{"type":"number","description":"share of the window the price spent in the range (a fraction: 0.42 = 42%)"},"asOf":{"type":"string","format":"date-time"},"net24h":{"oneOf":[{"type":"number","description":"the same range over the last 24 h (a fraction: 0.42 = 42%)"},{"type":"null"}]},"stakedEmissionApr":{"type":"number","description":"Slipstream gauge emissions if staked instead (informational) (a fraction: 0.42 = 42%)"}}}}},"Signal":{"type":"object","additionalProperties":true,"description":"Common fields below; the rest depends on `kind` (net_apr: net7d, net24h, fee7d, il7d, inRange7d, net30d; burst: netApr, windowHours, swaps; hot_pool: poolApr24h, poolApr7d; depeg: deviation, severe; tvl_outflow: drop, tvlBeforeUsd, tvlNowUsd; smart_lp: owner, …).","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["net_apr","burst","hot_pool","tvl_outflow","depeg","smart_lp"]},"firedAt":{"type":"string","format":"date-time"},"chain":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]},"pool":{"type":"string"},"pair":{"type":"string"},"dex":{"type":"string"},"fee":{"type":"integer"},"rangeBp":{"type":"integer"},"entryTick":{"type":"integer"},"tickLower":{"type":"integer"},"tickUpper":{"type":"integer"},"rule":{"oneOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},{"type":"null"}]},"outcome":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["done","inexact"]},"netApr":{"oneOf":[{"type":"number"},{"type":"null"}]},"feeApr":{"oneOf":[{"type":"number"},{"type":"null"}]},"ilApr":{"oneOf":[{"type":"number"},{"type":"null"}]},"evaluatedAt":{"type":"string"}}},{"type":"null"}]}}},"Account":{"type":"object","properties":{"id":{"type":"string"},"tier":{"type":"string","enum":["free","basic","pro"]},"paid":{"type":"boolean"},"telegramLinked":{"type":"boolean"},"webhookUrl":{"oneOf":[{"type":"string"},{"type":"null"}]},"walletAddress":{"oneOf":[{"type":"string"},{"type":"null"}]},"hasApiKey":{"type":"boolean"},"subscriptions":{"type":"array","items":{"type":"string"}}}},"RuleInput":{"type":"object","required":["name","kind"],"description":"kind net_apr needs minNet7d; depeg needs minDeviation; tvl_outflow needs minDrop. Thresholds are fractions.","properties":{"name":{"type":"string","maxLength":60},"kind":{"type":"string","enum":["net_apr","depeg","tvl_outflow"]},"enabled":{"type":"boolean"},"chains":{"type":"array","items":{"type":"string","enum":["ethereum","bsc","base","arbitrum","optimism","polygon","robinhood"]}},"pools":{"type":"array","items":{"type":"string","description":"\"<chain>:<address>\""},"maxItems":50},"pairClasses":{"type":"array","items":{"type":"string","enum":["stable","correlated","volatile"]}},"minTvlUsd":{"type":"number","minimum":100000},"cooldownHours":{"type":"integer","minimum":24,"maximum":720},"minNet7d":{"type":"number"},"minNet24h":{"type":"number"},"minInRange7d":{"type":"number"},"minDeviation":{"type":"number"},"minDrop":{"type":"number"},"windowHours":{"type":"integer","minimum":1,"maximum":24}}},"Rule":{"allOf":[{"$ref":"#/components/schemas/RuleInput"},{"type":"object","properties":{"id":{"type":"string"},"active":{"type":"boolean","description":"within the plan's limit (rules past it are kept but do not run)"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}]}}}}