{"openapi":"3.1.0","info":{"title":"IL Observer API","version":"1.0.0","description":"Read-only HTTP/JSON API for the IL Observer impermanent-loss tracker. Public, no authentication, no rate limit advertised. Source: https://github.com/ZaK3939/il-observer","contact":{"name":"IL Observer","url":"https://il-observer.io"},"license":{"name":"Public","url":"https://il-observer.io"}},"servers":[{"url":"https://il-observer.io","description":"Production"}],"paths":{"/api/health":{"get":{"summary":"Service health and feature flags","operationId":"getHealth","responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/protocols":{"get":{"summary":"Verified-demo registry and protocol coverage","operationId":"getProtocols","responses":{"200":{"description":"Protocol registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Protocols"}}}}}}},"/api/scan":{"post":{"summary":"Scan a wallet address for open LP positions","description":"Resolves the wallet's open LP positions, replays each one's lifecycle on-chain, and returns the canonical IL plus fees, rewards, and lifecycle events. Snapshots are cached per (chain, address) and reused unless `refresh: true` is set. On success, the response carries a `snapshotId` whose share page lives at `/s/<snapshotId>.html` and `/og/<snapshotId>.png`.","operationId":"scanAddress","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanRequest"},"examples":{"ekubo":{"summary":"Ekubo ETH / WBTC","value":{"address":"0xa0766fd5ecd0f472de2a77f9048653724fe2780f"}},"uniswap_v3":{"summary":"Uniswap V3 WETH / POLK","value":{"address":"0x1b84a9c353f4735853bdcf0a50f383e7aaf2cdff"}},"pancakeswap_v3":{"summary":"PancakeSwap V3 ETH / WBNB","value":{"address":"0x2b53795d0731461c835a129797b62178d9cccc2a"}},"sushiswap_v3":{"summary":"SushiSwap V3 WETH / USDT","value":{"address":"0x12ee177db3ceafedc639d023a29cc8588db3a4b9"}},"orca_whirlpool":{"summary":"Orca Whirlpool SOL / RENDER","value":{"address":"B5cYjddYUh6S4K7zo8nL4LLHYh48Ta4x6FM9Cvz6L7Pp"}},"raydium_clmm":{"summary":"Raydium CLMM SOL / CRCLX","value":{"address":"CcrknJyMF6AtAtr8xaV7a4BW6NiLNP5H9vo4SqhWHpE4"}},"uniswap_v4_vanilla":{"summary":"Uniswap V4 Vanilla ETH / GROW","value":{"address":"0xfebb27451296f94e8b2e26ad0fef098dafb760c0"}},"aerodrome_slipstream":{"summary":"Aerodrome Slipstream cbBTC / LBTC","value":{"address":"0x738e66480DF3A1B89778AC5557153878bC581fB9"}},"projectx":{"summary":"ProjectX WHYPE / USDC","value":{"address":"0x4d7c222e006cbe5f1bb9c81b38af6062c709764b"}}}}}},"responses":{"200":{"description":"Scan complete (found, not_found, or unsupported)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"400":{"description":"Malformed request body or unrecognized address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/x402/positions":{"get":{"summary":"Paid deep scan returning all renderable open positions","description":"GET-friendly x402 probe and paid deep scan. Without X-PAYMENT/PAYMENT-SIGNATURE the route returns HTTP 402 plus payment requirements, even before address validation, so agents can detect and fulfill x402 automatically.","operationId":"scanAllPositionsPaidGet","parameters":[{"name":"address","in":"query","required":true,"description":"EVM (0x…) or Solana wallet address","schema":{"type":"string"}},{"name":"protocols","in":"query","required":false,"description":"Comma-separated server protocol ids to limit the deep scan","schema":{"type":"string"}},{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"Base64-encoded x402 PaymentPayload. Legacy x402 clients may send the same payload as X-PAYMENT.","schema":{"type":"string"}}],"responses":{"200":{"description":"Deep scan complete or partial","headers":{"PAYMENT-RESPONSE":{"description":"Base64-encoded x402 settlement response","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsResponse"}}}},"400":{"description":"Malformed request body or unrecognized address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"x402 payment required or settlement rejected","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/X402PaymentRequired"}}}},"503":{"description":"x402 endpoint is not configured on this deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Paid deep scan returning all renderable open positions","description":"x402-protected endpoint for agents and API users that need a wallet's full set of strictly renderable open LP positions as JSON. Requests without a valid payment receive HTTP 402 with a PAYMENT-REQUIRED header. Paid responses include a PAYMENT-RESPONSE header from the settlement step.","operationId":"scanAllPositionsPaid","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"Base64-encoded x402 PaymentPayload. Legacy x402 clients may send the same payload as X-PAYMENT.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsRequest"},"examples":{"ekubo":{"summary":"Ekubo ETH / WBTC","value":{"address":"0xa0766fd5ecd0f472de2a77f9048653724fe2780f"}},"uniswap_v3":{"summary":"Uniswap V3 WETH / POLK","value":{"address":"0x1b84a9c353f4735853bdcf0a50f383e7aaf2cdff"}},"pancakeswap_v3":{"summary":"PancakeSwap V3 ETH / WBNB","value":{"address":"0x2b53795d0731461c835a129797b62178d9cccc2a"}},"sushiswap_v3":{"summary":"SushiSwap V3 WETH / USDT","value":{"address":"0x12ee177db3ceafedc639d023a29cc8588db3a4b9"}},"orca_whirlpool":{"summary":"Orca Whirlpool SOL / RENDER","value":{"address":"B5cYjddYUh6S4K7zo8nL4LLHYh48Ta4x6FM9Cvz6L7Pp"}},"raydium_clmm":{"summary":"Raydium CLMM SOL / CRCLX","value":{"address":"CcrknJyMF6AtAtr8xaV7a4BW6NiLNP5H9vo4SqhWHpE4"}},"uniswap_v4_vanilla":{"summary":"Uniswap V4 Vanilla ETH / GROW","value":{"address":"0xfebb27451296f94e8b2e26ad0fef098dafb760c0"}},"aerodrome_slipstream":{"summary":"Aerodrome Slipstream cbBTC / LBTC","value":{"address":"0x738e66480DF3A1B89778AC5557153878bC581fB9"}},"projectx":{"summary":"ProjectX WHYPE / USDC","value":{"address":"0x4d7c222e006cbe5f1bb9c81b38af6062c709764b"}}}}}},"responses":{"200":{"description":"Deep scan complete or partial","headers":{"PAYMENT-RESPONSE":{"description":"Base64-encoded x402 settlement response","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsResponse"}}}},"400":{"description":"Malformed request body or unrecognized address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"x402 payment required or settlement rejected","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/X402PaymentRequired"}}}},"503":{"description":"x402 endpoint is not configured on this deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/snapshot/{id}":{"get":{"summary":"Fetch a cached snapshot by id","operationId":"getSnapshot","parameters":[{"name":"id","in":"path","required":true,"description":"10-character lowercase hex snapshot id","schema":{"type":"string","pattern":"^[0-9a-f]{10}$"}}],"responses":{"200":{"description":"Snapshot found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanSnapshot"}}}},"400":{"description":"Malformed snapshot id (not a 10-char lowercase hex string)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Snapshot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Snapshot exists but is on an unsupported schema version","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/support-request":{"post":{"summary":"Submit a protocol-coverage request","description":"Used when a wallet returns no positions for a protocol the user expected. Best-effort logging only.","operationId":"submitSupportRequest","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportRequest"}}}},"responses":{"200":{"description":"Logged","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"requestId":{"type":"string","description":"Stable id of the persisted request"}},"required":["ok","requestId"]}}}},"400":{"description":"Body must include at least one of protocol, chain, or note","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"Health":{"type":"object","properties":{"ok":{"const":true},"node":{"type":"string"},"hasAnkr":{"type":"boolean"},"hasHelius":{"type":"boolean"},"hasAnthropic":{"type":"boolean"},"hasTelegramSupportRequests":{"type":"boolean"},"hasHyperevmRpc":{"type":"boolean"},"hasHyperevmRpcOverride":{"type":"boolean"},"verifiedDemoProtocols":{"type":"integer","minimum":0},"publicDemoProtocols":{"type":"integer","minimum":0},"trackedProtocols":{"type":"integer","minimum":0}},"required":["ok","node"]},"Protocols":{"type":"object","properties":{"ok":{"const":true},"summary":{"type":"object"},"protocols":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["verified","needs_live_candidate","adapter_not_ready","candidate_gate_only","not_wallet_scan_adapter"]},"serverProtocol":{"type":"string"},"resultCapability":{"type":"string"},"discoveryMode":{"type":"string"},"publicDemo":{"type":"boolean"},"address":{"type":"string"},"expected":{"type":["object","null"],"properties":{"scanStatus":{"type":"string"},"protocol":{"type":"string"},"pair":{"type":"string"}}}},"required":["id","status"]}}},"required":["ok","protocols"]},"ScanRequest":{"type":"object","properties":{"address":{"type":"string","description":"EVM (0x…) or Solana (base58) wallet address","minLength":32},"demoProtocolId":{"type":"string","description":"If set, scans only the candidate associated with this verified-demo id","nullable":true},"refresh":{"type":"boolean","description":"Bypass the cache and run a fresh scan","default":false}},"required":["address"]},"PositionsRequest":{"type":"object","properties":{"address":{"type":"string","description":"EVM (0x…) or Solana (base58) wallet address","minLength":32},"protocols":{"type":"array","description":"Optional server protocol ids to limit the deep scan","items":{"type":"string"}},"parallel":{"type":"boolean","description":"Run discovery/adapters in parallel; defaults to true","default":true}},"required":["address"]},"PositionsResponse":{"type":"object","properties":{"status":{"type":"string","enum":["complete","partial"]},"scannedAt":{"type":"string","format":"date-time"},"address":{"type":"string"},"chain":{"type":"string","enum":["evm","solana"]},"positions":{"type":"array","items":{"$ref":"#/components/schemas/RenderablePosition"}},"unavailable":{"type":"array","items":{"type":"object","properties":{"protocol":{"type":"string"},"chain":{"type":"string"},"status":{"type":"string"},"reason":{"type":"string"}}}},"summary":{"type":"object","properties":{"positionCount":{"type":"integer","minimum":0},"unavailableCount":{"type":"integer","minimum":0}}},"payment":{"type":"object","properties":{"protocol":{"const":"x402"},"payer":{"type":"string"},"network":{"type":"string"},"amount":{"type":"string"},"transaction":{"type":"string"}}}},"required":["status","scannedAt","address","chain","positions","unavailable","summary"]},"ScanResponse":{"type":"object","properties":{"status":{"type":"string","enum":["found","not_found"]},"snapshotId":{"type":"string","pattern":"^[0-9a-f]{10}$"},"fromCache":{"type":"boolean"},"snapshot":{"$ref":"#/components/schemas/ScanSnapshot"},"attempts":{"type":"array","items":{"type":"object","properties":{"protocol":{"type":"string"},"chain":{"type":"string"},"status":{"type":"string"},"reason":{"type":"string"}}}}},"required":["status","snapshotId"]},"ScanSnapshot":{"type":"object","properties":{"id":{"type":"string"},"scannedAt":{"type":"string","format":"date-time"},"address":{"type":"string"},"chain":{"type":"string","enum":["evm","solana"]},"schemaVersion":{"type":"integer"},"status":{"type":"string","enum":["found","not_found"]},"position":{"anyOf":[{"$ref":"#/components/schemas/RenderablePosition"},{"type":"null"}]},"verdict":{"type":["object","null"]}}},"RenderablePosition":{"type":"object","properties":{"protocol":{"type":"string"},"chain":{"type":"string"},"pair":{"type":"string"},"positionId":{"type":"string"},"rangeStatus":{"type":"string","enum":["in_range","below_range","above_range","unknown"]},"rangeWidth":{"type":"object","description":"Concentrated-liquidity tick span and equivalent price-width percent","properties":{"widthTicks":{"type":"number"},"widthMultiplier":{"type":"number"},"widthPct":{"type":"number"},"lowerTick":{"type":"number"},"upperTick":{"type":"number"},"tickSpacing":{"type":"number"},"tickBase":{"type":"number"},"protocolId":{"type":"string"}}},"hodlUsd":{"type":"number"},"principalUsd":{"type":"number"},"netUsd":{"type":"number"},"feesUsd":{"type":"number"},"rewardsUsd":{"type":"number"},"claimedFeesUsd":{"type":"number"},"claimedFeesConfidence":{"type":"string"},"claimedRewardsUsd":{"type":"number"},"claimedRewardsConfidence":{"type":"string"},"canonicalIl":{"type":"object","properties":{"status":{"type":"string"},"classification":{"type":"string"},"valueUsd":{"type":"number"},"pct":{"type":"number"}}},"singleAssetHodl":{"type":["object","null"],"description":"Optional comparison vs holding 100% of either token at entry"},"qualityNotes":{"type":"array","items":{"type":"string"}}}},"X402PaymentRequired":{"type":"object","properties":{"x402Version":{"const":2},"error":{"type":"string"},"resource":{"type":"object","properties":{"url":{"type":"string"},"description":{"type":"string"},"mimeType":{"type":"string"}}},"accepts":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string"},"network":{"type":"string"},"asset":{"type":"string"},"amount":{"type":"string"},"payTo":{"type":"string"},"maxTimeoutSeconds":{"type":"integer"}}}}},"required":["x402Version","resource","accepts"]},"SupportRequest":{"type":"object","properties":{"protocol":{"type":"string"},"chain":{"type":"string"},"address":{"type":"string"},"note":{"type":"string"},"attempts":{"type":"array","items":{"type":"object"}}}}}}}