接入文档
FurryFans 开放能力通过 furface.furryfans.cn 提供 HTTP API。 所有请求使用 AK/SK 签名鉴权 —— 没有 Bearer 模式,没有降级路径。
服务与端点
| 服务 | 端点 | 说明 |
|---|---|---|
| FurFind 毛毛定位 | POST /v1/detect | 返回画面中每个兽装的边界框与置信度 |
| Furface 识兽 | POST /v1/analyze | 检测 + 识别一体,返回角色候选 |
POST /v1/recognize | 对给定 bbox 只做识别(detect 的输出框可直接回喂) |
密钥归属单一产品:FurFind 的密钥只能调 /v1/detect, Furface 的密钥只能调 /v1/analyze 与 /v1/recognize。
请求格式
入图两种方式,二选一:
- JSON 体:
{"imageUrl": "https://..."} - multipart:
image字段直传文件(≤ 20MB)
/v1/recognize 额外需要 boxes(JSON 数组,元素为 {x, y, width, height},坐标按响应中 imgW/imgH 的解码空间,最多 100 个)。
签名算法
每个请求携带四个头:
| Header | 内容 |
|---|---|
X-Ffs-Key | 密钥 ID(ffs_ 开头,公开可入日志) |
X-Ffs-Timestamp | Unix 秒。允许与服务器偏移 ±300s |
X-Ffs-Nonce | 随机串,≤32 字符,窗口内不可重复 |
X-Ffs-Sign | 签名(hex 小写) |
签名构造(六段以换行符 \n 连接):
StringToSign = METHOD # 大写,如 POST path # 如 /v1/analyze canonical_query # query 参数按 key 排序后 k=v&k=v 重拼,无则空串 sha256(body) # 请求体的 SHA-256 hex;空体对空字节算 timestamp # 与 X-Ffs-Timestamp 一致 nonce # 与 X-Ffs-Nonce 一致 X-Ffs-Sign = hex(HMAC-SHA256(secret_key, StringToSign))
Python 示例
import hashlib, hmac, time, uuid, requests
KEY_ID = "ffs_xxxxxxxx" # 控制台创建密钥时获得
SECRET = "<你的 Secret,仅创建时显示一次>"
def sign_headers(method: str, path: str, body: bytes) -> dict:
ts = str(int(time.time()))
nonce = uuid.uuid4().hex[:16]
sts = "\n".join([
method.upper(), path, "", # 无 query 时第三段为空串
hashlib.sha256(body).hexdigest(),
ts, nonce,
])
sig = hmac.new(SECRET.encode(), sts.encode(), hashlib.sha256).hexdigest()
return {
"X-Ffs-Key": KEY_ID, "X-Ffs-Timestamp": ts,
"X-Ffs-Nonce": nonce, "X-Ffs-Sign": sig,
}
body = b'{"imageUrl": "https://example.com/photo.jpg"}'
r = requests.post(
"https://furface.furryfans.cn/v1/analyze",
data=body,
headers={**sign_headers("POST", "/v1/analyze", body),
"Content-Type": "application/json"},
)
print(r.json())错误响应
失败返回 {"ok": false, "error": {"code", "message", ...}}, 按 code 分类处理:
| code | HTTP | 含义与处理 |
|---|---|---|
sign-mismatch | 401 | 签名不匹配。响应附 string_to_sign_template,对照检查拼接顺序 |
timestamp-expired | 401 | 时钟偏移超限。响应附 server_time,可自动校准 |
nonce-replayed | 401 | nonce 重复。换新 nonce 重试 |
key-revoked | 401 | 密钥已吊销。重试无意义 |
wrong-service | 403 | 密钥不属于该服务。在对应服务下创建密钥 |
payment-required | 402 | 今日免费额度用尽且余额不足 |
image-too-large | 413 | 图片超 20MB |
计费
- 每个服务有每日免费额度(创建第一个密钥即生效),先扣免费次数,用尽后按次从钱包扣费。
- 仅成功调用(2xx)计费;参数错误(4xx)不计费;服务端错误(5xx)自动退款。
- 余额即人民币。费率见账单页,不同接口费率不同(纯检测低于识别)。