Webhook实现指南
注册一个HTTPS URL,当智能资金信号触发时接收实时HMAC签名的事件推送——无需轮询。本指南涵盖注册、事件过滤、签名验证及重试机制。
概述
替代轮询 /v1/confirm 或信号订阅,注册一个Webhook后,当匹配信号触发时,Smart Money API会立即向您的终端POST一个事件。每次投递均使用HMAC-SHA256签名,以便您验证其真实来源。
出站Webhook适用于 专业版 和企业版套餐。
注册Webhook
向 /v1/webhooks 发起POST请求,并在 X-API-Key 请求头中携带您的API密钥。请求体需包含四个字段:
| 字段 | 类型 | 说明 |
| url | 字符串 | 接收事件的HTTPS终端地址(必须以 https://) |
| events | 数组 | 要接收的事件名称,例如 ["HIGH","MEDIUM","VETO"] 或 ["*"] |
| symbols | 数组 | 用于过滤的交易对,例如 ["BTC","ETH"] 或 ["*"] |
| secret | 字符串 | 您的签名密钥—— 至少16位字符。存储时已哈希处理;请保留原始值用于验证签名。 |
curl -X POST https://api.smartmoneyapi.com/v1/webhooks \
-H "X-API-Key: sm_your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/smartmoney",
"events": ["HIGH", "MEDIUM"],
"symbols": ["BTC", "ETH"],
"secret": "a-long-random-secret-16-plus-chars"
}'
{
"webhook_id": 42,
"url": "https://yourapp.com/webhooks/smartmoney",
"events": ["HIGH", "MEDIUM"],
"symbols": ["BTC", "ETH"],
"message": "Webhook注册成功。使用POST /v1/webhooks/test进行测试"
}
事件过滤器
仅当事件名称和交易对匹配您的注册条件时才会触发投递。典型事件名称为确认置信度等级—— HIGH, MEDIUM, VETO ——以及通用 SIGNAL 事件。使用 ["*"] 可接收所有事件或所有交易对。
投递与请求头
每次投递均为HTTP POST 请求,包含JSON正文及以下请求头:
| Header | Value |
| X-SmartMoney-Event | 事件名称(例如 HIGH) |
| X-SmartMoney-Signature | 请求体的HMAC-SHA256十六进制摘要(见下文) |
| Content-Type | application/json |
| User-Agent | SmartMoneyAPI-Webhook/1.0 |
{
"event": "HIGH",
"ts": "2026-07-01T18:22:05Z",
"symbol": "BTC",
"direction": "long",
"confidence": "HIGH",
"composite": 0.74,
"webhook_id": 42
}
响应任意 2xx 状态以确认。非2xx(或超时)将触发重试。
验证签名
中的签名 X-SmartMoney-Signature 是请求体的HMAC-SHA256十六进制摘要。 HMAC密钥是您注册的机密的SHA-256十六进制摘要 (您的原始机密仅以哈希形式存储在我们这边)。要验证:派生密钥,对原始体进行HMAC,并与恒定时间检查进行比较。拒绝任何失败的请求。
import hashlib, hmac
from flask import Flask, request, abort
app = Flask(__name__)
MY_SECRET = "a-long-random-secret-16-plus-chars" # 您注册的值
@app.post("/webhooks/smartmoney")
def receive():
raw = request.get_data() # 请求体的确切字节
sig = request.headers.get("X-SmartMoney-Signature", "")
key = hashlib.sha256(MY_SECRET.encode()).hexdigest() # HMAC密钥 = sha256(secret)十六进制
expected = hmac.new(key.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
abort(401)
event = request.get_json()
# ... 根据event["event"], event["symbol"], event["composite"]进行操作 ...
return "", 200
import crypto from "crypto";
import express from "express";
const app = express();
const MY_SECRET = "a-long-random-secret-16-plus-chars";
// 捕获原始体以便签名检查使用确切的字节。
app.post("/webhooks/smartmoney", express.raw({ type: "*/*" }), (req, res) => {
const sig = req.get("X-SmartMoney-Signature") || "";
const key = crypto.createHash("sha256").update(MY_SECRET).digest("hex");
const expected = crypto.createHmac("sha256", key).update(req.body).digest("hex");
const ok = expected.length === sig.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
if (!ok) return res.status(401).end();
const event = JSON.parse(req.body.toString());
// ... 根据event进行操作 ...
res.status(200).end();
});
验证 原始、未解析的 请求体 — 重新序列化解析后的JSON可能会改变字节顺序或间距,从而破坏检查。
重试
如果您的端点未返回 2xx (或超时——交付超时时间为10秒),Smart Money API会以指数退避方式重试最多3次(大约1秒、4秒,然后16秒)。请确保您的处理程序具有幂等性,以便安全地重复处理重新投递的事件。
入站Webhooks(TradingView)
另外,您可以向我们发送一条 入站 警报。 POST /v1/tradingview/webhook 接收到TradingView警报后,会通过 /confirm进行处理,并返回确认信息。由于TradingView无法发送自定义标头,因此通过JSON正文中的 secret 字段进行身份验证(而非 X-API-Key)。发送 secret, symbol,以及 direction (long/short);可选地 timeframe, strategy,和 price.