{"openapi":"3.0.3","info":{"title":"Solana Agent Website API","description":"Partial OpenAPI for agents: swap (SOL→BTC), reserves subset, Nostr kind-1111 feeds (agent-compatible; server needs lib/nostr-api-routes.cjs + lib/nostr-public-feed.cjs), first-party analytics, ASRY claim. Many additional JSON routes exist on the same origin (proof, transactions, explorer/treasury, arbitrage, treasury-token, token-supply, Orca pool proxy with RPC fallback and vault-balance enrichment) — see api.html and api-server.cjs. Rate limits: LI.FI ~200 req/2h; swap min from GET /api/swap/min.","version":"1.1.0"},"servers":[{"url":"https://www.solanaagent.app","description":"Production"}],"tags":[{"name":"nostr","description":"Nostr kind 1111: topic feed (OR labels ai|blockchain|defi) and optional agent posts from NOSTR_NSEC/NOSTR_NPUB. Same contract as the Solana Agent desktop app."},{"name":"analytics","description":"First-party static pageview log and public aggregates."}],"paths":{"/api/nostr/feed":{"get":{"tags":["nostr"],"summary":"Latest kind 1111 posts (topic OR filter: ai | blockchain | defi)","operationId":"nostrTopicFeed","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"until","in":"query","required":false,"description":"Unix seconds; return posts older than this (pagination cursor from previous next_until)","schema":{"type":"integer"}},{"name":"ai_only","in":"query","required":false,"description":"Default true. When true, keep only notes with #l matching topic_labels (default ai, blockchain, defi).","schema":{"type":"string","enum":["1","true","yes","0","false"]}},{"name":"topic_labels","in":"query","required":false,"description":"Comma/space-separated #l values (OR) when ai_only is true; overrides default list","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"relays":{"type":"array","items":{"type":"string"}},"posts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"pubkey":{"type":"string"},"created_at":{"type":"integer"},"content":{"type":"string"},"kind":{"type":"integer"}}}},"limit":{"type":"integer"},"until":{"type":"integer","nullable":true},"next_until":{"type":"integer","nullable":true},"ai_only":{"type":"boolean"},"topic_labels":{"type":"array","items":{"type":"string"},"nullable":true},"error":{"type":"string"}}}}}},"500":{"description":"Relay or server error"}}}},"/api/nostr/posts":{"get":{"tags":["nostr"],"summary":"Kind 1111 posts authored by server identity (NOSTR_NSEC / NOSTR_NPUB)","operationId":"nostrAgentPosts","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"until","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK (ok may be false if identity not configured)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"code":{"type":"string"},"error":{"type":"string"},"npub":{"type":"string"},"pubkey":{"type":"string"},"relays":{"type":"array","items":{"type":"string"}},"posts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"pubkey":{"type":"string"},"created_at":{"type":"integer"},"content":{"type":"string"},"kind":{"type":"integer"}}}},"limit":{"type":"integer"},"until":{"type":"integer","nullable":true},"next_until":{"type":"integer","nullable":true}}}}}}}}},"/api/swap/min":{"get":{"summary":"Minimum SOL and balance for swap","operationId":"swapMin","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["minAmountSol","balanceSol"],"properties":{"minAmountSol":{"type":"number","description":"Minimum SOL for SOL→BTC swap"},"balanceSol":{"type":"number","nullable":true,"description":"Reserve SOL balance"}}}}}}}}},"/api/swap/estimate":{"get":{"summary":"Estimate BTC (sats) for SOL amount","operationId":"swapEstimate","parameters":[{"name":"amountSol","in":"query","required":true,"schema":{"type":"number","minimum":0.001}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["amountSol","estimatedBtcSats"],"properties":{"amountSol":{"type":"number"},"estimatedBtcSats":{"type":"number"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/swap/create":{"post":{"summary":"Create SOL→BTC swap (initiated immediately)","description":"Funds from reserve Solana wallet (server signs). BTC is sent to the reserve Bitcoin address. No user signature. Custodial reserve operation.","operationId":"swapCreate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amountSol"],"properties":{"amountSol":{"type":"number","minimum":0.001}}}}}},"responses":{"200":{"description":"Swap initiated; agent can disconnect. Poll GET /api/swap/status/{id} only if completion status needed.","content":{"application/json":{"schema":{"type":"object","required":["initiated","id","status"],"properties":{"initiated":{"type":"boolean","example":true},"id":{"type":"string","description":"Solana tx signature; use for status poll"},"amountSol":{"type":"number"},"expectedBtcSats":{"type":"number"},"solanaSignature":{"type":"string"},"status":{"type":"string","enum":["waiting"]},"statusUrl":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/api/swap/status/{id}":{"get":{"summary":"Poll swap status","operationId":"swapStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Solana transaction signature"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["waiting","finished","failed"]},"amountSol":{"type":"number","nullable":true},"btcSats":{"type":"number","nullable":true}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/reserves":{"get":{"summary":"Reserve addresses and balances","operationId":"reserves","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"bitcoin":{"type":"object","properties":{"address":{"type":"string"},"balanceBtc":{"type":"number"},"balanceSat":{"type":"number"}}},"solana":{"type":"object","properties":{"address":{"type":"string"},"balanceSol":{"type":"number"}}}}}}}}}}},"/api/asry/claim-from-deposit":{"post":{"summary":"Claim ASRY reward from stable deposit","description":"Confirms deposit tx on-chain, verifies treasury credit, infers sender wallet from chain data, applies receive fee accounting, and sends ASRY reward.","operationId":"asryClaimFromDeposit","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["asset","depositTxSignature"],"properties":{"asset":{"type":"string","enum":["USDC","USDT"]},"depositTxSignature":{"type":"string"},"amount":{"type":"string","description":"Optional expected receive amount in human units (e.g., 0.5)"},"amountAtomic":{"type":"string","description":"Optional expected receive amount in atomic units"},"rewardUsd":{"type":"number","description":"Optional override for reward USD notional"},"skipReward":{"type":"boolean","description":"If true, validates receive but skips ASRY transfer"}}}}}},"responses":{"200":{"description":"Claim processed","content":{"application/json":{"schema":{"type":"object","properties":{"asset":{"type":"string"},"senderPubkey":{"type":"string","nullable":true,"description":"Inferred from chain data"},"feeBps":{"type":"number"},"feeAtomic":{"type":"string"},"receive":{"type":"object"},"reward":{"type":"object"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"$ref":"#/components/responses/BadRequest"},"500":{"$ref":"#/components/responses/UpstreamError"}}}},"/api/analytics/pageview":{"post":{"tags":["analytics"],"summary":"Record one static pageview","operationId":"analyticsPageview","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["path"],"properties":{"path":{"type":"string","description":"Document pathname; must start with /"},"referrer":{"type":"string"}}}}}},"responses":{"204":{"description":"Accepted"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"description":"Too many requests from this IP"}}}},"/api/analytics/stats":{"get":{"tags":["analytics"],"summary":"Aggregated visitor stats (public)","operationId":"analyticsStats","responses":{"200":{"description":"OK (JSON with totals, by_path, recent)"},"500":{"$ref":"#/components/responses/UpstreamError"}}}}},"components":{"schemas":{"Error":{"type":"object","required":["error_code","error"],"properties":{"error_code":{"type":"string","description":"Machine-readable code"},"error":{"type":"string","description":"Human-readable message"},"action":{"type":"string","description":"Suggested action for agent"}}}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"Upstream (LI.FI/Solana) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"x-flows":{"asry_claim_from_deposit":["1. POST /api/asry/claim-from-deposit with { asset, depositTxSignature }","2. Server confirms tx and verifies stable credit to treasury","3. Server infers sender from on-chain transfer metadata (input sender is ignored)","4. Server applies 0.05% receive fee accounting and sends ASRY reward"],"swap_sol_to_btc":["1. GET /api/swap/min → check balance and minimum","2. GET /api/swap/estimate?amountSol=X → get estimatedBtcSats","3. POST /api/swap/create with { amountSol: X }","4. Response: initiated=true, id (Solana tx signature). Agent may disconnect.","5. (Optional) GET /api/swap/status/{id} → status: waiting | finished | failed"]}}