{"openapi":"3.1.0","info":{"title":"SolGov Public API","version":"1.0.0","description":"Live Solana governance state across 50+ DeFi protocols.\n\n**Data freshness**\n- Live multisig state (threshold, members, timelock, configAuthority): refreshed within ~30 minutes.\n- Activity feed (`/alerts/recent`): real-time, append-only as events land on-chain.\n- Historical aggregates (`/historical`): refreshed weekly; expect up to 7 days of lag.\n\n**Scope**\nCoverage is the protocols solgov actively tracks. Protocols outside that set are not represented; absence in the response does not imply absence on chain. The `governanceModel` field on each protocol indicates the underlying governance pattern: `squads-v4`, `squads-v3`, `serum-multisig`, `realms-dao`, `wormhole-guardians`, `single-signer`, etc. Protocols without a Squads multisig (e.g. single-signer, DAO-governed) return `threshold: 0, totalMembers: 0` because there is no multisig to count; consult `governanceModel` to interpret.\n\n**Rate limits**\nReads: 60 requests / minute / IP. Writes (POST/DELETE): 10 requests / minute / IP. Limits surface as `X-RateLimit-*` headers and 429 / 503 responses with `Retry-After`.\n\n**Corrections**\nFound a discrepancy? DM @Trader_CSK on X.","contact":{"name":"SolGov","url":"https://solgov.xyz"}},"servers":[{"url":"https://solgov.xyz"}],"paths":{"/api/v1/protocols":{"get":{"summary":"List tracked protocols","description":"Sorted list of every protocol solgov currently monitors. Includes derived `canonical` and `role` fields so secondary multisigs (treasury, governance) roll up to the parent protocol.","responses":{"200":{"description":"Sorted list of protocol names with canonical mapping"}}}},"/api/v1/governance":{"get":{"summary":"Live governance slice for every tracked protocol","description":"One row per tracked protocol with current threshold, signer count, timelock, configAuthority, pending proposals, threat alerts, last program upgrade and governance model. Refreshed within ~30 minutes. Each row also includes `lastChecked` and `stalenessHours` so freshness is self-reporting. `pendingProposals` counts Squads proposals that are open or approved, not executed, and can still execute (the scanner checks Squads rules and every deploy buffer, target account and authority a proposal needs); null when that scan is unavailable. `lastUpgradeAt` is the latest deploy across the protocol's programs, read from each program's ProgramData.","parameters":[{"name":"protocols","in":"query","schema":{"type":"string"},"description":"Comma-separated names to filter (case-insensitive substring match)"}],"responses":{"200":{"description":"Map of protocol to governance slice"}}}},"/api/v1/governance/{protocol}":{"get":{"summary":"Single-protocol governance slice (with members)","description":"Same shape as `/governance` but for one protocol. Adds the full member list, threat alert detail, program upgrade authorities and `governanceModel`, plus:\n- `queuedProposals`: each proposal that can still execute (`status` approved or proposed, approvals/threshold, kind, programId, detail).\n- `lastUpgrade` `{ at, programId }` and `programs[]` `{ programId, name, lastDeployedAt, upgradeAuthority, sizeKB }`, read from ProgramData every 3 hours.\n- `activity`: counts read from the headline multisig's full on-chain history (refreshed daily): `created`, `totalTxs`, `configChanges`, `configDates`, members added/removed, threshold and timelock changes, `approvedProposals` (proposals executed), `rejectedProposals` (rejected and never executed), `cancelledProposals`, `proposers`/`approvers`/`executors` (distinct signers), `activeVoters90d`, `neverSignedCount`, proposal-to-execution hours and `offHoursConfigChanges` (22:00-06:00 UTC). Keyed to the multisig address it was read from.\nName match is case-insensitive with substring fallback. Fields whose source scan is unavailable are null.","parameters":[{"name":"protocol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Governance slice"},"404":{"description":"Protocol not tracked"}}}},"/api/v1/alerts/recent":{"get":{"summary":"Recent governance events feed (real-time)","description":"Append-only event log of every governance change observed across all tracked protocols. Events are produced in real time as on-chain transactions land. Newest first. Capped at 500 entries; rolls over.","parameters":[{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO 8601. Filter to events with timestamp >= this value."},{"name":"protocol","in":"query","schema":{"type":"string"},"description":"Case-insensitive substring match against protocol name."},{"name":"type","in":"query","schema":{"type":"string"},"description":"Filter by event type, e.g. `ConfigChange`, `ProgramUpgrade`, `Approval`."},{"name":"limit","in":"query","schema":{"type":"integer","maximum":500,"default":50}}],"responses":{"200":{"description":"Filtered event list, newest first"}}}},"/api/v1/search":{"get":{"summary":"Resolve a base58 address to protocols","description":"Looks up which tracked protocol a Solana address appears in, as a multisig signer or program upgrade authority. Searches against current live state only; does not search historical signers who have since been removed.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Solana base58 pubkey to resolve"}],"responses":{"200":{"description":"List of protocol/role pairs the address appears in"}}}},"/api/v1/state":{"get":{"summary":"Full monitor state (heavy)","description":"Complete state object: every tracked protocol's live multisig data, plus the recent activity log and optional scanner outputs under underscore keys (_daos, _oracles, _oracleConfig, _composability, _independence, _pendingUpgrades, _verifiedBuilds, _tokenTransparency, _adminPath, _publicCommitsAhead, _govActivity, _programDeploys, _integrity) and `_meta` provenance (generatedAt, stateFileWrittenAt). `_govActivity.entries` is keyed by multisig address; `_programDeploys` holds per-program deploy dates and authorities, latest deploy per protocol, and role-multisig configurations. Each protocol's `pendingProposals` is the count of proposals that can still execute (see `/governance`). ~150 KB response. Prefer `/governance` or `/governance/{protocol}` for normal use; `/state` is intended for the dashboard and bulk integrations.","responses":{"200":{"description":"Complete state object"}}}},"/api/v1/historical":{"get":{"summary":"Scan-derived aggregates (refreshed weekly)","deprecated":true,"description":"Deprecated: the scan behind this endpoint is no longer run, and some entries describe multisigs that protocols have since replaced. Use the `activity` field of `/governance/{protocol}` (or `_govActivity` in `/state`), which is read from each current multisig's full on-chain history and refreshed daily. Kept for existing clients; each entry has its own `lastUpdated` timestamp.","responses":{"200":{"description":"Historical aggregates per protocol, with per-entry lastUpdated"}}}},"/api/v1/health":{"get":{"summary":"Freshness of every data surface","description":"Reports each data surface the API serves (live multisig state, integrity scan, activity log, governance activity, program deploys, independence scores, pending upgrades, verified builds, token transparency, oracle reads, DAO risk, admin path, public commits) with its last stamp, age in hours and whether it is stale against the cadence its producer is expected to run on. `status` is `ok` when nothing is stale and `degraded` otherwise; `staleSurfaces` lists the names. Intended for client-side freshness assertions and for catching a stopped cron.","responses":{"200":{"description":"Per-surface freshness report"}}}},"/api/v1/stride":{"get":{"summary":"Mapping of solgov fields to STRIDE governance controls","description":"solgov's mapping of the on-chain facts it publishes to the STRIDE Governance controls (G1 to G5) defined by Asymmetric Research for the Solana Foundation. Vocabulary alignment only: no maturity level or score is asserted for any protocol. Includes the source URL.","responses":{"200":{"description":"Control-to-evidence mapping"}}}},"/api/v1/changelog/{protocol}":{"get":{"summary":"Permanent per-protocol change history","description":"Every governance event recorded for one protocol (config changes, signer changes, timelock changes, program upgrades, proposals), newest first. Matches the base protocol name and any program-suffixed variant such as \"Raydium (LaunchLab)\". Use `?limit=` up to 500. Each event is citable by its timestamp, type and detail.","parameters":[{"name":"protocol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":500}}],"responses":{"200":{"description":"Events for the protocol"},"400":{"description":"Missing protocol"}}}},"/api/v1/cadence":{"get":{"summary":"Program upgrade cadence per protocol","description":"For each protocol: upgrades observed, first and last observed, count in the last 30 days and the mean interval in days. Derived from confirmed ProgramUpgrade events (deploy-slot verified) in the activity log; the same upgrade reported by the real-time listener and the daily digest is counted once. Covers the activity log window (roughly a year), not lifetime totals.","responses":{"200":{"description":"Cadence per protocol"}}}},"/api/v1/badge/{protocol}.json":{"get":{"summary":"shields.io endpoint badge","description":"A shields.io endpoint-badge payload stating the protocol's current multisig threshold and timelock, e.g. \"4/7 multisig, 24h timelock\". Colour is always neutral; the badge implies no grade. Embed with https://img.shields.io/endpoint?url=https://solgov.xyz/api/v1/badge/Kamino.json","parameters":[{"name":"protocol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"shields.io endpoint schema"}}}},"/api/v1/feed.xml":{"get":{"summary":"RSS 2.0 feed of governance events","description":"The last 50 public activity events as RSS, for Telegram, Discord and Farcaster relays. Each item links to the protocol changelog.","responses":{"200":{"description":"RSS XML"}}}},"/api/v1/track":{"get":{"summary":"List user-tracked Squads v4 multisigs currently being monitored","responses":{"200":{"description":"Array of {address, label, addedAt}, with cap and current count"}}},"post":{"summary":"Submit any Squads v4 multisig address for live monitoring","description":"Validates on-chain that the address is a Squads v4 multisig before adding. Monitoring for new addresses begins within ~60 seconds. Subscribe to alerts via the Telegram bot or POST /api/webhooks afterwards.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["address"],"properties":{"address":{"type":"string","description":"Solana base58 pubkey of the Squads v4 multisig account"},"label":{"type":"string","description":"Optional display label, max 60 chars"}}}}}},"responses":{"201":{"description":"Added; verification metadata returned"},"400":{"description":"Bad address, not on-chain, or not a Squads v4 multisig"},"409":{"description":"Tracking cap reached"},"503":{"description":"On-chain validation temporarily unavailable"}}}},"/api/webhooks":{"post":{"summary":"Subscribe to push delivery","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"protocols":{"type":"array","items":{"type":"string"},"description":"omit or empty for all"},"severities":{"type":"array","items":{"type":"string","enum":["CRITICAL","HIGH","MONITOR"]}},"types":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Subscription created. Response includes the secret used to verify deliveries."}}}},"/api/webhooks/{id}":{"get":{"summary":"View subscription config","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"secret","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Subscription record"},"404":{"description":"Not found or wrong secret"}}},"delete":{"summary":"Unsubscribe","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"secret","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found or wrong secret"}}}}}}