Skip to content

反詐欺資料 API ​

資料 API 是 Web SDK 的伺服器端搭檔。用它來拉取裁決、彙總統計、匯出資料, 用於報表與對帳——拉取你自己系統據以一致的那些數字。

基礎 URL ​

https://verify.captcha.la

鑑權 ​

所有資料 API 請求都用你的反詐欺應用程式憑證鑑權,以請求標頭形式傳送:

X-App-Key:    YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET

WARNING

X-App-Secret 僅限伺服器端。絕不要把它暴露給瀏覽器、行動端或公開儲存庫。 頁面 SDK 始終只使用公開的 appKey。

端點 ​

取得單條裁決 ​

取得某一次訪問的裁決(例如用於對帳某次具體訪問)。必須傳一個識別碼:verdict_id(頁面收到的裁決裡帶的)或 cid(點擊 ID,用於帶 click token 的流量)。

bash
GET /v1/bot/verdict?verdict_id=VERDICT_ID
GET /v1/bot/verdict?cid=CID_OF_THE_VISIT
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET

found 表示是否找到。為 true 時,data 是裁決欄位參考裡說明的各欄位:

json
{
  "found": true,
  "data": {
    "cid": null,
    "verdict_id": "vd_3f9c0a7e5b1d4c2a9e8f7b6a",
    "is_bot": true,
    "score": 87,
    "level": "high",
    "action": "flag",
    "reasons": ["automation", "network"],
    "consistency": { "ok": false },
    "degraded": false,
    "created_at": "2026-06-25 00:00:00"
  }
}

沒有符合時回傳 {"found": false}。verdict_id 和 cid 都不傳的請求回傳 HTTP 400。

TIP

裁決在產生後幾秒內才會入庫,訪問剛結束就查詢可能回傳 found: false。需要即時判斷時請用校驗裁決憑證。

校驗裁決憑證 ​

校驗頁面從 Web SDK 拿到的 verdict_token,用於在伺服器端做內容牆(見伺服器端校驗)。結果即時回傳,不依賴入庫資料。

bash
POST /v1/bot/verdict/verify
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
Content-Type: application/json

{ "token": "vt1.eyJ2Ijoi...", "ip": "203.0.113.7", "consume": false }
參數必填說明
token是裁決裡的 verdict_token。
ip否你的伺服器端看到的訪客 IP。傳了之後,token 必須來自與本次訪問相同的網路。建議傳。
consume否true = token 只能用一次,第二次校驗回傳 already_used。預設 false:過期前可以反覆校驗。
json
{
  "valid": true,
  "error": null,
  "verdict_id": "vd_3f9c0a7e5b1d4c2a9e8f7b6a",
  "expired": false,
  "expires_at": 1767225600,
  "ip_match": true,
  "verdict": {
    "is_bot": false,
    "level": "low",
    "action": "record_only",
    "score": 12,
    "degraded": false,
    "reasons": [],
    "issued_at": 1767225000
  }
}
欄位說明
validtoken 真實、屬於你的應用程式、未過期、與 ip 相符(若傳了),並且在 consume 模式下未被用過時為 true。valid 只說明 token 是真的,不代表訪客是真人,還要看 verdict。
errornull,或 token 無效的原因:malformed、bad_signature、expired、ip_mismatch、already_used、unavailable(一次性校驗暫時無法完成,請重試)。
expired / expires_at是否過期,以及過期時間(Unix 秒)。
ip_match傳了 ip 時為 true / false,否則為 null。
verdict簽章裡的裁決:is_bot、level、action、score、degraded、reasons、issued_at。token 無法解析時為 null。

常見做法:valid 為 true 且 verdict.is_bot 為 false 時回傳內容。verdict.degraded 為 true,以及請求根本沒帶 token 時怎麼處理,由你決定:選擇放行,服務故障時真實訪客仍能訪問;選擇拒絕,沒有有效 token 就一律拒絕。

token 預設 10 分鐘過期。需要新 token 時重新執行 SDK 即可(例如下一次頁面載入)。

彙總統計 ​

按時間範圍拉取計數(總量、機器人數,以及按 level 和按天的拆分),用於看板與品質報表。

bash
GET /v1/bot/stats?from=2026-06-01&to=2026-06-30
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
json
{
  "from": "2026-06-01",
  "to": "2026-06-30",
  "cleaned": true,
  "total": 124500,
  "bots": 18230,
  "by_level": { "low": 100300, "medium": 16900, "high": 6200, "critical": 1100 },
  "by_day": [
    { "date": "2026-06-01", "total": 4100, "bots": 590 }
  ]
}

from / to 預設最近 7 天。

匯出 ​

按時間範圍匯出逐次訪問的裁決列,用於離線對帳。按時間倒序分頁回傳。

bash
GET /v1/bot/export?from=2026-06-01&to=2026-06-30&limit=1000
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
參數說明
from / to日期範圍(YYYY-MM-DD),選填。
limit每頁列數,1–5000(預設 1000)。
cursor傳上一頁的 next_cursor 取下一頁。
json
{
  "rows": [
    {
      "id": 1042, "cid": null, "verdict_id": "vd_3f9c0a7e5b1d4c2a9e8f7b6a",
      "is_bot": false, "score": 12, "level": "low", "action": "record_only",
      "reasons": [], "consistency": { "ok": true }, "degraded": false,
      "created_at": "2026-06-25 00:00:00", "rescored": false
    }
  ],
  "next_cursor": 1042
}

每一列攜帶該次訪問的識別碼、時間戳記和裁決欄位,你可據此與自己的日誌關聯。最後一頁的 next_cursor 為 null。

已清洗口徑

統計與匯出預設按已清洗口徑回傳:事後識別為無效的流量會被持續重新評估並從數字中 剔除。該過程非同步進行,因此非常近期時段的數字可能仍會小幅收斂。傳 ?raw=1 可查看 未清洗的原始口徑;在 export 中,每一列還會攜帶 rescored 標記。

逐點擊對帳

對於付費流量場景,一次訪問可以回溯到某次具體投遞的點擊,供雙方就此結算。這用到 點擊 token,見廣告反作弊指南。

Click token 參考(給流量方) ​

流量方在自己的伺服器上簽一枚 click token,加到目標 URL 上,這樣這次造訪的裁決就能歸屬回該流量方。簽名是離線的——不需要呼叫 API。

取得簽名憑證 ​

在 dashboard 裡開啟你的 app → 反詐欺 → 簽發簽名金鑰,會得到:

  • bot_kid —— 你的公開 key id(作為 token 裡的 pkid)。
  • bot_hmac_secret —— 你的簽名 secret,只顯示一次,務必存在伺服器端。

Token 格式 ​

ct.<base64url(payload)>.<base64url(HMAC_SHA256(body, bot_hmac_secret))>

body 是 JSON payload 的 base64url;簽名對該 body 字串計算。

payload 欄位 ​

欄位必填說明
pkid是你的 bot_kid;後端據此反查你的 secret 驗簽
cid是本次點擊的唯一 id,對帳主鍵。每次點擊產生全新唯一值
aud否目標廣告主的 app_key。設了之後 token 只在該廣告主頁面被承接;不設則任意廣告主頁面都可承接
click_ts否點擊發生的 unix 秒
exp否unix 秒過期時間;過期 token 被拒

加到連結上 ​

把 token 作為 _ctk 查詢參數加到廣告主目標 URL:

https://advertiser.example/lp?_ctk=ct.<...>.<...>

廣告主的 SDK 會自動讀取 _ctk(可用 tokenParam 設定參數名)。每個 cid 都有防重放保護:同一訪客重新整理頁面不受影響,token 被拿到別處重複使用會被標記。見 安全模型。

範例(虛擬碼) ​

js
const payload = { pkid, cid, aud: advertiserAppKey, click_ts: now, exp: now + 900 }
const body  = base64url(JSON.stringify(payload))
const sig   = base64url(hmacSha256(body, botHmacSecret))
const token = `ct.${body}.${sig}`
const url   = `${destination}?_ctk=${encodeURIComponent(token)}`

Postback(伺服器端到伺服器端推送) ​

除了輪詢資料 API,你還可以讓裁決在產生時主動推送到你自己的端點—— 對希望即時記錄/對帳每次訪問的聯盟 tracker 和廣告主伺服器端很方便。

啟用 ​

在 dashboard 裡開啟你的 app → 反詐欺 → 設定 Postback URL (bot_postback_url)。設定之後,每條裁決都會在產生後不久 POST 到該 URL。 推送是非同步且隔離的——端點慢或失敗,絕不影響已回傳給頁面 SDK 的裁決。

推送時機 ​

每次產生該 app 裁決的 verify 都會觸發。推送盡力而為,帶少量自動重試; 按 至少一次 語意處理,以 verdict_id 去重。

請求 ​

POST <你的 bot_postback_url>
Content-Type: application/json
X-Bot-Signature: t=<unix_ts>,v=<hex>

Body(JSON):

json
{
  "cid": "CID_OF_THE_VISIT",
  "verdict_id": "vd_3f9c0a7e5b1d4c2a9e8f7b6a",
  "is_bot": 1,
  "score": 87,
  "level": "high",
  "action": "flag",
  "advertiser_app_id": 12,
  "provider_app_id": 34,
  "created_at": "2026-06-25 00:00:00"
}
欄位說明
cid本次訪問的對帳主鍵(無 click token 時可能為 null)
verdict_id裁決 ID,與頁面收到的一致
is_bot1 / 0
score風險分
levellow / medium / high / critical
action伺服器端權威 action(record_only / flag / challenge / deny)
advertiser_app_id本次 verify 所屬 app 的 id
provider_app_id經 click token 歸屬時的流量方 id,否則為 null
created_at裁決時間(UTC)

驗簽 ​

X-Bot-Signature 標頭讓你確認請求確實來自我們。格式為 t=<unix_ts>,v=<hex>,其中:

hex = HMAC_SHA256( "<unix_ts>." + 原始請求體 , bot_hmac_secret )

bot_hmac_secret 就是你在反詐欺 → 簽發簽名金鑰 拿到的那枚簽名 secret。 驗簽時對收到的原始 body 重新計算 HMAC(不要把 JSON 重新序列化),以常數時間比較。 可選擇拒絕 t 與本機時鐘偏差過大的請求以限制重放。

js
// Express 範例
const [tsPart, vPart] = req.get('X-Bot-Signature').split(',')
const ts = tsPart.slice(2)             // 去掉 "t=" 前綴
const v  = vPart.slice(2)              // 去掉 "v=" 前綴
const expected = crypto
  .createHmac('sha256', BOT_HMAC_SECRET)
  .update(ts + '.' + rawBody)          // rawBody 是未解析的原始請求體
  .digest('hex')
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v))

下一步 ​

MIT-licensed examples · CaptchaLa is operated independently