APK 與網站檢測 API

網站檢測同步回傳 JSON;APK 可透過檔案上傳、完整特徵或套件名稱非同步檢測,結果送至已驗證的簽章 Webhook。

開始使用

概覽

網站檢測會在請求內同步完成;APK 檢測採非同步掃描與簽章回呼。所有檢測端點共用帳號會員頻率視窗。

01提交

傳送檢測請求或先直傳 APK

02審查

驗證特徵、去重並執行掃描

03輪詢 / 回呼

輪詢 GET /api/v1/jobs/{job_id},或同時接收簽章 Webhook

APK API 支援輪詢

受理回應包含 job_id,可用 GET /api/v1/jobs/{job_id} 輪詢約 24 小時。callback_url 可選;提供時同時投遞簽章 Webhook。

JSON · common APK fields
{
  "client_reference": "order-20260711-001",
  "callback_url": "https://example.com/webhooks/fvl",
  "use_cache": false
}
存取控制

驗證

每次請求使用以下任一標頭。金鑰只在建立時完整顯示,必須保存在伺服器端。

建議Authorization: Bearer fvl_xxx
相容X-API-Key: fvl_xxx

請勿將 API 金鑰寫入瀏覽器、行動應用程式、公開儲存庫或日誌。

存取控制

額度與頻率

API 僅開放給 VIP+、SVIP、SVIP+ 與管理員;同一帳號的所有 API Key 共用頻率視窗。

身分組最短間隔R2 每日上傳額度
VIP+10 分鐘2 GiB
Pro3 分鐘5 GiB
SVIP5 分鐘10 GiB
SVIP+1 分鐘30 GiB
管理員不限不限
網站檢測、APK 上傳工作階段建立、APK 特徵與套件名稱檢測共用帳號頻率;快取命中、冪等重播與在途任務合併不會重複開啟視窗。
每位使用者最多保留 1 個有效未完成上傳工作階段。建立 R2 工作階段時會預扣一次複檢並占用頻率視窗,簽發後不退還。
API

端點

除預簽章 R2 PUT 步驟外,所有請求與回應皆使用 JSON。

POST/api/v1/url-scan同步檢測網站

傳入 url,在同一回應取得風險結果與扣次後 quota;不使用 Webhook。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/url-scan \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/path"}'
HTTP 200
{
  "code": 0,
  "message": "success",
  "data": {
    "result": {
      "status": "completed",
      "url": "https://example.com/path",
      "domain": "example.com",
      "flagged": false,
      "mainType": 0,
      "mainTypeName": "安全",
      "provider": "OPPO",
      "websiteType": 0,
      "matchUrl": "",
      "riskDetail": "",
      "cacheStatus": "live",
      "checkedAt": 1783765471000,
      "createdAt": 1783765471000
    },
    "quota": {
      "identity_label": "VIP+",
      "daily_limit": 20,
      "daily_used": 1,
      "daily_remaining": 19,
      "scan_credits": 0,
      "total_remaining": 19,
      "usage_date": "2026-07-11"
    }
  }
}
POST/api/v1/apk/uploads建立 APK 上傳工作階段

需要 Idempotency-Key、.apk 檔名、size、file_md5、expected_sha256 與共用回呼欄位;上傳網址有效 30 分鐘。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/apk/uploads \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: upload-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "order-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": false,
    "filename": "release.apk",
    "size": 24117384,
    "file_md5": "0123456789abcdef0123456789abcdef",
    "expected_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
  }'
PUT · R2 required_headers
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/vnd.android.package-archive" \
  -H "Content-Length: 24117384" \
  -H "Content-MD5: ASNFZ4mrze8BI0VniavN7w==" \
  -H "If-None-Match: *" \
  --upload-file ./release.apk
POST/api/v1/apk/uploads/complete完成上傳並提交審查

傳入 upload_token 與 Idempotency-Key。平台驗證物件並提交已預付審查,不會再次扣次。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/apk/uploads/complete \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: order-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{"upload_token":"upl_xxxxxxxxxxxxxxxx"}'
POST/api/v1/apk/fingerprints提交 APK 特徵

傳入 package_name、sha256、file_md5、cert_md5 與共用回呼欄位,無需再次上傳 APK。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/apk/fingerprints \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: fingerprint-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "fingerprint-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": true,
    "package_name": "com.example.app",
    "sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    "file_md5": "0123456789abcdef0123456789abcdef",
    "cert_md5": "abcdef0123456789abcdef0123456789",
    "version_code": 108,
    "version_name": "1.0.8",
    "size": 24117384,
    "filename": "release.apk"
  }'
POST/api/v1/packages/check檢測套件名稱

快速核驗裝置端套件名稱風險;不等同包含檔案雜湊與憑證的完整 APK 掃描。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/packages/check \
  -H "X-API-Key: fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: package-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "package-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": false,
    "package_name": "com.example.app"
  }'
HTTP 202
{
  "code": 0,
  "message": "accepted",
  "data": {
    "client_reference": "order-20260711-001",
    "job_id": "acd_xxxxxxxxxxxxxxxx",
    "delivery": "webhook_and_poll",
    "poll_path": "/api/v1/jobs/acd_xxxxxxxxxxxxxxxx"
  }
}
GET/api/v1/jobs/{job_id}輪詢非同步任務

使用受理回應中的 job_id 查詢 pending / processing / completed / failed;結果約保留 24 小時。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/packages/check \
  -H "X-API-Key: fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: package-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "package-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": false,
    "package_name": "com.example.app"
  }'
HTTP 202
{
  "code": 0,
  "message": "accepted",
  "data": {
    "client_reference": "order-20260711-001",
    "job_id": "acd_xxxxxxxxxxxxxxxx",
    "delivery": "webhook_and_poll",
    "poll_path": "/api/v1/jobs/acd_xxxxxxxxxxxxxxxx"
  }
}
API

簽發前預扣,簽發後不退還

簽發前預扣,簽發後不退還

平台先驗證會員、帳號頻率、複檢額度、每日上傳位元組額度與未完成工作階段數,再預扣一次複檢並簽發 URL。未完成、過期、雜湊不符、非法 APK 或佇列失敗均不退還。暫時入列失敗會保留樣本並由持久化任務自動重試。

樣本保留政策

合法 APK 依 SHA-256 去重封存;無效或不一致樣本進入 quarantine,兩者保留 90 天。未完成上傳 1 天後自動清除。

請求控制

use_cache 語意

use_cache 位於 JSON 根層,預設 false。R2 上傳無論值為何都會在簽發 URL 前預扣;此欄位僅控制完成後是否可重用結果。

false強制複檢

false 會略過既有結果,實際開始掃描時扣一次複檢。

cache_status = bypass
true允許快取

true 命中有效快取時直接回呼且不扣次;未命中或過期時自動複檢。

cache_status = hit | miss
結果傳送

簽章 Webhook

Webhook 是 APK 非同步檢測的唯一結果通道。伺服器傳送原始 JSON 位元組、時間戳與 HMAC-SHA256 簽章。

X-FVL-TimestampX-FVL-Timestamp: 1720000000
X-FVL-SignatureX-FVL-Signature: sha256=<hex>
  1. 計算 webhook_secret = lowercase_hex(SHA-256(raw_api_key))。
  2. 簽章輸入為 X-FVL-Timestamp + "." + raw_body。
  3. 以 webhook_secret 的 UTF-8 位元組計算 HMAC-SHA256,並以固定時間比較簽章。
  4. 驗證時間戳並回傳任意 2xx;非 2xx 會觸發重試。
Webhook JSON
{
  "event": "apk.scan.completed",
  "client_reference": "order-20260711-001",
  "operation": "apk_upload",
  "status": "completed",
  "cache_status": "bypass",
  "result": { "flagged": false, "result_type_name": "安全" },
  "quota": { "refresh_daily_remaining": 29, "total_remaining": 29 },
  "checked_at": "2026-07-11T10:24:31.000Z"
}
Node.js · HMAC-SHA256
import crypto from "node:crypto";

export function verifyFvlWebhook(rawBody, timestamp, signature, apiKey) {
  const webhookSecret = crypto
    .createHash("sha256")
    .update(apiKey, "utf8")
    .digest("hex");
  const expected = "sha256=" + crypto
    .createHmac("sha256", webhookSecret)
    .update(timestamp + "." + rawBody)
    .digest("hex");

  const expectedBytes = Buffer.from(expected, "utf8");
  const signatureBytes = Buffer.from(signature, "utf8");

  return expectedBytes.length === signatureBytes.length &&
    crypto.timingSafeEqual(expectedBytes, signatureBytes);
}

必須先讀取 raw body 再解析 JSON;重新序列化會改變位元組並導致驗章失敗。

請求控制

冪等與去重

建立上傳工作階段、完成上傳、特徵檢測與套件名稱檢測必須提供 Idempotency-Key。

相同金鑰與相同請求在 24 小時內回傳相同結果且不重複扣次。
相同金鑰對應不同請求會回傳 HTTP 409。
同一資產的並行複檢合併為一次掃描,每個呼叫仍收到自己的 Webhook。
參考

錯誤碼

同步錯誤使用 HTTP 狀態碼與統一 JSON。非同步 APK 審查失敗透過 scan.failed Webhook 回傳。

HTTP含義處理方式
400請求或欄位無效修正 JSON、雜湊、套件名稱或回呼網址。
401驗證失敗檢查 API 金鑰。
403無權呼叫檢查會員方案與到期時間。
409狀態衝突檢查冪等金鑰或上傳狀態。
429額度或頻率受限依 Retry-After 稍後重試。
503服務暫時無法使用依端點規則以相同冪等金鑰重試。
Node.js
const body = {
  client_reference: "package-20260711-001",
  callback_url: "https://api.example.com/webhooks/fvl",
  use_cache: true,
  package_name: "com.example.app"
};

const response = await fetch(
  "https://www.fuckviruslabel.com/api/v1/packages/check",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer " + process.env.FVL_API_KEY,
      "Content-Type": "application/json",
      "Idempotency-Key": body.client_reference
    },
    body: JSON.stringify(body)
  }
);

if (!response.ok) throw new Error(await response.text());
console.log(await response.json());
Python
import os
import requests

payload = {
    "client_reference": "package-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": True,
    "package_name": "com.example.app",
}

response = requests.post(
    "https://www.fuckviruslabel.com/api/v1/packages/check",
    headers={
        "Authorization": f"Bearer {os.environ['FVL_API_KEY']}",
        "Idempotency-Key": payload["client_reference"],
    },
    json=payload,
    timeout=20,
)
response.raise_for_status()
print(response.json())
機器可讀 OpenAPI 3.1用於產生用戶端、驗證請求或匯入 API 工具。
參考

變更記錄

v1.0.0

檢測 API 首次發布:網站檢測、R2 上傳、APK 特徵、套件名稱檢測、快取、冪等與簽章 Webhook。