Webhooks

當你建立含有 webhook URL 的 agent 時,Cursor 會發送 HTTP POST 請求來通知你狀態變更。目前僅支援 statusChange 事件,適用於 agent 進入 ERRORFINISHED 狀態時。

Webhook 驗證

為了確保 webhook 請求確實來自 Cursor,請驗證每個請求所附帶的簽名:

標頭

每個 webhook 請求都會包含以下標頭:
  • X-Webhook-Signature – 以 sha256=<hex_digest> 格式提供 HMAC-SHA256 簽名
  • X-Webhook-ID – 此次投遞的唯一識別碼(有助於記錄)
  • X-Webhook-Event – 事件類型(目前僅有 statusChange
  • User-Agent – 固定為 Cursor-Agent-Webhook/1.0

簽名驗證

要驗證 webhook 簽名,請計算預期簽名並與收到的簽名比對:
const crypto = require('crypto');

function verifyWebhook(secret, rawBody, signature) {
  const expectedSignature = 'sha256=' + 
    crypto.createHmac('sha256', secret)
          .update(rawBody)
          .digest('hex');
  
  return signature === expectedSignature;
}
import hmac
import hashlib

def verify_webhook(secret, raw_body, signature):
    expected_signature = 'sha256=' + hmac.new(
        secret.encode(),
        raw_body,
        hashlib.sha256
    ).hexdigest()
    
    return signature == expected_signature
計算簽名時,請務必使用原始請求主體(在任何解析之前)。

負載格式

Webhook 會以 JSON 格式傳送負載,結構如下:
{
  "event": "statusChange",
  "timestamp": "2024-01-15T10:30:00Z",
  "id": "bc_abc123",
  "status": "FINISHED",
  "source": {
    "repository": "https://github.com/your-org/your-repo",
    "ref": "main"
  },
  "target": {
    "url": "https://cursor.com/agents?id=bc_abc123",
    "branchName": "cursor/add-readme-1234",
    "prUrl": "https://github.com/your-org/your-repo/pull/1234"
  },
  "summary": "Added README.md with installation instructions"
}
注意:部分欄位是選填,僅在有值時才會包含。

最佳實務

  • 驗證簽章 – 一定要驗證 webhook 簽章,確保請求來自 Cursor
  • 處理重試 – 如果你的端點回傳錯誤狀態碼,webhook 可能會重試送出
  • 快速回應 – 儘快回傳 2xx 狀態碼
  • 使用 HTTPS – 在正式環境的 webhook 端點一律使用 HTTPS URL
  • 儲存原始載荷 – 將原始 webhook 載荷保存下來,方便偵錯與後續驗證