00

API

JSON over HTTPS. Every response is { version, data }. Pass x-api-key for paid tiers; anonymous use is limited to 30 requests a minute.

Endpoints

GET/api/v1/protocolsAll watched protocols with grade, score, flags and key facts.
GET/api/v1/protocols/:slugOne protocol including the full control snapshot.
GET/api/v1/protocols/:slug/eventsGovernance timeline for a protocol.
GET/api/v1/events?severity=high&since=ISOEvents across protocols, filtered by minimum severity and time.
GET/api/v1/scores/:slug/historyScore history.
GET/api/v1/streamServer-Sent Events: event, score, registry, shield.
POST/api/v1/subscriptions/webhookCreate a webhook. Returns the signing secret once.
POST/api/v1/subscriptions/testTest-fire a webhook with a signed sample payload.

Examples

curl
curl -s https://<host>/api/v1/protocols/drift -H "x-api-key: $OVERWATCH_KEY" \
  | jq '.data | {grade, score, flagNames, threshold, timelockSec}'

curl -s "https://<host>/api/v1/events?severity=critical&since=2026-10-01T00:00:00Z"

curl -N https://<host>/api/v1/stream   # event: event / score / registry / shield
create a webhook
curl -X POST https://<host>/api/v1/subscriptions/webhook \
  -H 'content-type: application/json' \
  -d '{"url":"https://example.com/hooks/overwatch",
       "min_severity":"HIGH",
       "protocols":["drift","kamino-lend"]}'

Webhook signatures

Each delivery is signed: x-overwatch-signature = hex(HMAC-SHA256(secret, rawBody)). Failed deliveries retry with exponential backoff, up to 6 attempts.

verify.ts
import { verifyWebhook } from "@overwatch/sdk";

const ok = await verifyWebhook(rawBody, req.headers["x-overwatch-signature"], process.env.OVERWATCH_SECRET);
if (!ok) return new Response(null, { status: 401 });

Onchain: read the registry from your program

The RiskRecord PDA is ["risk", sha256(slug)] under the registry program. Check the owner and the PDA, then test flags & RED_MASK.

lib.rs
#[account(seeds = [b"risk", protocol_id.as_ref()], bump = risk.bump,
          seeds::program = overwatch_registry::ID)]
pub risk: Account<'info, overwatch_registry::RiskRecord>,   // owner checked by Account<>
...
if risk.flags & overwatch_registry::flags::RED_MASK != 0 { /* exit */ }
sdk.ts
import { fetchRiskRecord } from "@overwatch/sdk";

const r = await fetchRiskRecord("https://api.devnet.solana.com", "drift");
// { score, grade, flags, red, ... }