Guide · FAssets
Monitor FAssets agent liquidation risk programmatically
FAssets agents mint wrapped XRP (FXRP) on Flare mainnet against vault and pool collateral. If an agent's collateral ratio drops below its mintingCR threshold, the protocol can liquidate the vault to make redeemers whole. This guide shows how to pull the current risk state for every agent over a plain HTTP request, and wire it into a Discord or Slack alert in about forty lines of Python.
No auth, no API key. All data is public and updated every 60 seconds from Flare mainnet.
The risk bands
FlareForge classifies every tracked agent into one of five bands based on the cushion between its current vault collateral ratio and its own mintingCR threshold, plus its on-chain status.
- safe— vault CR is at least 50 percentage points above mintingCR.
- warning— cushion between 15 and 50 percentage points.
- danger— cushion below 15 percentage points. Minting is getting tight.
- critical— vault CR below mintingCR, OR the AssetManager reports the agent in LIQUIDATION or FULL_LIQUIDATION, OR the on-chain
liquidationStartTimestampis non-zero. - unknown— we haven't indexed a CR snapshot yet (new agent, or indexer lag).
Aggregate risk in one call
The cheapest way to get a health snapshot of every agent at once:
curl https://flareforge.io/api/v1/agents/risk-summary | jqReturns:
{
"total": 6,
"counts": {
"safe": 6,
"warning": 0,
"danger": 0,
"critical": 0,
"unknown": 0
},
"worst_offenders": [],
"updated_at": "2026-04-19T09:00:00+00:00"
}worst_offenders is a short list of agents currently classified danger or critical, already sorted by severity, with the fields you need to open a detail page or send an alert.
Per-agent detail
The /v1/agents list (and /v1/agents/{address} detail) response now includes three risk fields alongside the existing collateral data:
{
"address": "0xA69b...9fe3",
"display_name": "Bifrost Wallet",
"asset_type": "FXRP",
"collateral_ratio_bips": 24000,
"minting_cr_bips": 14000,
"risk_level": "safe",
"risk_headroom_bips": 10000,
"risk_reason": "100.0 pp cushion over mintingCR"
}risk_headroom_bips is vault_cr - minting_crin basis points (1 bip = 0.01%). It's null when the agent is already in liquidation, because there is no meaningful cushion left to report.
Discord alert in 40 lines of Python
Below is a self-contained script. It polls the risk-summary endpoint and pings a Discord webhook every time a new agent enters danger or critical. State is a single JSON file on disk, so it survives restarts and doesn't alert twice for the same agent.
import json
import time
from pathlib import Path
from urllib.request import Request, urlopen
API = "https://flareforge.io/api/v1/agents/risk-summary"
WEBHOOK = "https://discord.com/api/webhooks/XXXX/YYYY"
STATE_FILE = Path("fassets_alerts_state.json")
ALERT_LEVELS = {"danger", "critical"}
def load_state() -> dict:
if STATE_FILE.exists():
return json.loads(STATE_FILE.read_text())
return {"alerted": {}}
def save_state(state: dict) -> None:
STATE_FILE.write_text(json.dumps(state))
def fetch_summary() -> dict:
with urlopen(API, timeout=10) as resp:
return json.loads(resp.read())
def notify(message: str) -> None:
body = json.dumps({"content": message}).encode("utf-8")
req = Request(WEBHOOK, data=body, headers={"Content-Type": "application/json"})
with urlopen(req, timeout=5) as resp:
resp.read()
def tick() -> None:
state = load_state()
summary = fetch_summary()
for agent in summary["worst_offenders"]:
if agent["risk_level"] not in ALERT_LEVELS:
continue
previous = state["alerted"].get(agent["address"])
if previous == agent["risk_level"]:
continue
notify(
f"FAssets agent {agent['display_name']} is now **{agent['risk_level']}**. "
f"Headroom: {agent['risk_headroom_bips']} bips."
)
state["alerted"][agent["address"]] = agent["risk_level"]
save_state(state)
if __name__ == "__main__":
while True:
try:
tick()
except Exception as err:
print(f"tick failed: {err}")
time.sleep(60)Replace the WEBHOOKconstant with your Discord or Slack URL and run it anywhere. Sixty-second polling is fine — the indexer itself runs at the same cadence, so polling more aggressively just returns the same data.
TypeScript / Node variant
import { writeFileSync, readFileSync, existsSync } from "node:fs";
const API = "https://flareforge.io/api/v1/agents/risk-summary";
const WEBHOOK = "https://discord.com/api/webhooks/XXXX/YYYY";
const ALERT_LEVELS = new Set(["danger", "critical"]);
const STATE_FILE = "fassets_alerts_state.json";
type Offender = {
address: string;
display_name: string;
risk_level: string;
risk_headroom_bips: number | null;
};
async function tick(): Promise<void> {
const state: Record<string, string> = existsSync(STATE_FILE)
? JSON.parse(readFileSync(STATE_FILE, "utf8"))
: {};
const res = await fetch(API);
const summary = (await res.json()) as { worst_offenders: Offender[] };
for (const a of summary.worst_offenders) {
if (!ALERT_LEVELS.has(a.risk_level)) continue;
if (state[a.address] === a.risk_level) continue;
await fetch(WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: `FAssets agent ${a.display_name} is now **${a.risk_level}**. Headroom: ${a.risk_headroom_bips} bips.`,
}),
});
state[a.address] = a.risk_level;
}
writeFileSync(STATE_FILE, JSON.stringify(state));
}
setInterval(() => tick().catch(console.error), 60_000);What the scoring does and doesn't cover
The cushion is computed against the agent's self-declared mintingCR, not the system-wide minimum or liquidation trigger, because each agent can set its own mintingCR above the floor. That's a conservative choice: an agent can still be safely above the liquidation floor while we already report "danger", because the agent itself stopped minting.
We only look at vault collateral today. Pool collateral (native FLR) is also tracked by the AssetManager, and a full risk picture would combine both. The simpler vault-only view is still directional and catches the fast-moving failure mode (vault token price drop against the underlying).
If you want to reproduce the scoring yourself, the classification logic is open and tested. See the on-site Agent Monitor for the human-facing version, or plug the API into whatever ops stack you already run.
Related endpoints
GET /api/v1/agents— every indexed agent with risk fields attached.GET /api/v1/agents/{address}/history?hours=24— collateral-ratio history, useful for graphing a single agent over time.GET /api/v1/network/fassets/summary?network=flare— aggregate FAssets throughput (mints, redemptions, liquidations in the last 24h).