Watchdog API
Slot 容量、具名收件人、告警以及带签名的 Webhook。
最近更新: 2026年9月30日使用 GET /api/x402/pricing 和订阅报价端点获取当前产品、Watch 类型、信号、默认值和折扣。付费类型消耗各自的产品容量;免费类型有每钱包的限制。已暂停的 Watch 仍然计数。用 spend 购买;用 write 创建或更改 Watch。创建 Watch 不是订阅购买。
curl 'https://ftso.app/api/x402/subscriptions/quote?product=watchdog-slot&quantity=5&periods=12' \
-H 'authorization: Bearer fbx_READ_TOKEN'
curl -X POST 'https://ftso.app/api/x402/subscriptions' \
-H 'authorization: Bearer fbx_SPEND_TOKEN' \
-H 'content-type: application/json' \
-H 'Idempotency-Key: purchase_20260930_001' \
-d '{"product":"watchdog-slot","quantity":5,"periods":12,"autoRenew":true}'Auto-Renew 按当前价格重复已购买的数量和期限。开启它需要 spend;关闭它需要 write。购买前可能需要先接受现有条款。一次性试用可通过 POST /api/x402/subscriptions/trial 获得,须满足资格条件。
curl -X POST 'https://ftso.app/api/x402/watches' \
-H 'authorization: Bearer fbx_WRITE_TOKEN' \
-H 'content-type: application/json' \
-H 'Idempotency-Key: watch_20260930_001' \
-d '{"type":"feed-move","label":"FLR swing",
"config":{"chainId":14,"symbol":"FLR","percent":2.5,"windowMinutes":60},
"signals":{"price-move":{"enabled":true}}}'
curl -X PATCH 'https://ftso.app/api/x402/watches/7' \
-H 'authorization: Bearer fbx_WRITE_TOKEN' -H 'content-type: application/json' \
-d '{"action":"pause"}'PATCH 支持 config、signals、routing、label、cooldownSeconds、messageTemplate、webhookUrl、rotateSecret 以及 pause/resume 操作。config 更改会重置监控状态。信号覆盖按字段合并;null 重置一个覆盖。signalsMode: replace 替换全部覆盖,而在默认的 merge 下,空的 signals 对象不做任何更改。密钥轮换和首次 Webhook 设置会返回一个密钥:请安全地存储它。在 24 小时的幂等保留期内,同一 key 的重放可能再次返回它。
具名收件人可在多个 Watch 之间复用。机器客户端可以创建输入型通道;关联型通道遵循各自的验证和权限规则。Discord 关联仍然仅限会话。待处理的收件人不能接收告警或测试。旧版通道端点指向其类型中最早的收件人;为精确控制请优先使用收件人 ID。Webhook URL 在读取时被掩码:省略 target 会保留它,明确以空值/null 移除会清除它。不要把显示用的掩码作为新 URL 写回。
curl -X POST 'https://ftso.app/api/x402/recipients' \
-H 'authorization: Bearer fbx_WRITE_TOKEN' -H 'content-type: application/json' \
-d '{"name":"Ops","type":"webhook","target":{"url":"https://example.com/hooks/ftsobest"}}'
# Use the returned recipient id in routing.
curl -X PATCH 'https://ftso.app/api/x402/watches/7' \
-H 'authorization: Bearer fbx_WRITE_TOKEN' -H 'content-type: application/json' \
-d '{"routing":{"default":["inapp",12],"groups":{"alerts":[12]}}}'信号组路由覆盖 Watch 的默认设置;默认收件人是回退方案。账户/系统事件始终送达铃铛通知以及明确设为默认的收件人。信号告警的铃铛投递可以关闭。免打扰时段会暂扣个人通道;组、Webhook 和铃铛继续投递。Watch 的 Cooldown 抑制同一事件的重复,不会抑制不同事件或其恢复。
curl -X PUT 'https://ftso.app/api/x402/settings' \
-H 'authorization: Bearer fbx_WRITE_TOKEN' -H 'content-type: application/json' \
-d '{"quietHours":{"start":"22:00","end":"07:00","timezone":"Europe/Berlin"},"notificationLocale":"de"}'
curl -X POST 'https://ftso.app/api/x402/message-preview' \
-H 'authorization: Bearer fbx_READ_TOKEN' -H 'content-type: application/json' \
-d '{"watchId":7,"notificationLocale":"de","scope":"wallet","messageTemplate":null}'模板包含 title、body 和 appendDetails。Watch 模板覆盖钱包模板;null 恢复默认值。占位符是纯文本替换,绝不是可执行标记。允许的占位符:{watch}、{type}、{title}、{severity}、{emoji}、{network}、{identity}、{round}、{epoch}、{details}、{time}、{link}。预览不会投递消息。
curl 'https://ftso.app/api/x402/alerts?page=0&pageSize=20&watchId=7&severity=warning&delivery=failed&sort=time&direction=desc' \
-H 'authorization: Bearer fbx_READ_TOKEN'
curl 'https://ftso.app/api/x402/alerts/export?watchId=7' \
-H 'authorization: Bearer fbx_READ_TOKEN'历史使用从零开始的页码,pageSize 最大为 100。导出使用相同的筛选条件,最多返回 5,000 行 CSV。Watch 列表和账户列表改用 limit/cursor。他人的 Watch 或告警 ID 返回 404。删除 Watch 不会抹除其告警历史。删除告警是一个明确的 write 操作;选择条件和 maxId 保护预期的历史窗口。
载荷 v2 在 v1 结构上新增 payloadVersion: 2、signal 和 group。即使渲染文本已本地化,技术字段也保持不变。请阅读 v2 Schema,并接受事件数据中的额外字段。按 deliveryId 去重。下方生成的事件列表涵盖已编目的信号事件和恢复事件;账户消息和通道测试是独立的系统事件。
这个简化后的 v2 示例展示了封装结构;data 包含与类型相关的具体信息。v1 Schema 使用相同的核心字段 delivery、alert、watch、event、severity、firedAt 和 data,但没有 v2 新增的三个字段。rendered 和 renderedMessage 可提供本地化的显示文本;请保留 deliveryId 用于去重。
{
"payloadVersion": 2,
"deliveryId": "unique-delivery-id",
"alertId": 41,
"watchId": 7,
"label": "FLR swing",
"type": "feed-move",
"event": "feed-move.threshold",
"signal": "price-move",
"group": "alerts",
"severity": "warning",
"firedAt": "2026-09-30T12:00:00.000Z",
"data": {}
}import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody is the exact request body Buffer, not parsed/re-serialized JSON.
const timestamp = req.headers["x-watchdog-timestamp"];
const signature = req.headers["x-watchdog-signature"];
if (
typeof timestamp !== "string" ||
!/^\d+$/.test(timestamp) ||
typeof signature !== "string" ||
Math.abs(Date.now() / 1000 - Number(timestamp)) > 300
)
throw new Error("invalid");
const expected = Buffer.from(
"sha256=" +
createHmac("sha256", secret)
.update(timestamp + ".")
.update(rawBody)
.digest("hex"),
);
const received = Buffer.from(signature);
if (received.length !== expected.length || !timingSafeEqual(expected, received))
throw new Error("invalid");验证使用 X-Watchdog-Signature 和 X-Watchdog-Timestamp;通过 X-Watchdog-Payload-Version 查看载荷契约。只有在验证签名和时效性之后才响应。对重复的 deliveryId 予以确认,但不要重复执行效果。更完整的工作流程参见 Watchdog 用户文档。
- credits.low-balance
- credits.recovered
- feed-move.threshold
- fsp.balance-low
- fsp.balance-low.recovered
- fsp.fast-updates
- fsp.fast-updates.recovered
- fsp.fdc-bitvote
- fsp.fdc-bitvote-length
- fsp.fdc-bitvote-length.recovered
- fsp.fdc-bitvote.recovered
- fsp.fdc-consensus
- fsp.fdc-consensus.recovered
- fsp.fdc-reveal-offence
- fsp.fdc-reveal-offence.recovered
- fsp.fdc-signature
- fsp.fdc-signature.recovered
- fsp.fdc-submit1
- fsp.fdc-submit1.recovered
- fsp.ftso-commit
- fsp.ftso-commit.recovered
- fsp.ftso-reveal
- fsp.ftso-reveal.recovered
- fsp.ftso-signature
- fsp.ftso-signature.recovered
- fsp.mc-anchor
- fsp.mc-anchor.recovered
- fsp.mc-fdc
- fsp.mc-fdc.recovered
- fsp.mc-uptime
- fsp.mc-uptime.recovered
- fsp.monitoring
- fsp.monitoring.recovered
- fsp.not-in-policy
- fsp.not-in-policy.recovered
- fsp.registration
- fsp.registration.recovered
- fsp.reveal-offence
- fsp.reveal-offence.recovered
- fsp.rewards-unclaimed
- fsp.rewards-unclaimed.recovered
- fsp.signature-grace
- fsp.signature-grace.recovered
- fsp.signature-mismatch
- fsp.signature-mismatch.recovered
- fsp.tx-failed
- fsp.tx-failed.recovered
- fsp.validator-not-listed
- fsp.validator-not-listed.recovered
- provider.eligibility-lost
- provider.recovered
- provider.unregistered
- signing.done
- signing.missed
- signing.rewards-open
- signing.rewards-reminder
- signing.uptime-open
- wallet-balance.moved