跳轉到主要內容

Webhooks

當你用 webhook URL 建立 agent 時,Cursor 會送出 HTTP POST 請求來通知狀態變更。目前只支援 statusChange 事件,也就是在 agent 進入 ERRORFINISHED 狀態時。

Webhook 驗證

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

Headers

每個 webhook 請求都會包含以下標頭:
  • X-Webhook-Signature – 含有 HMAC-SHA256 簽名,格式為 sha256=<hex_digest>
  • 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": "狀態變更",
  "timestamp": "2024-01-15T10:30:00Z",
  "id": "bc_abc123",
  "status": "完成",
  "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": "新增含安裝說明的 README.md"
}
請注意,部分欄位為選填,僅在有資料時才會包含。

最佳實務

  • 驗證簽章 – 一定要驗證 webhook 簽章,確保請求來自 Cursor
  • 處理重試 – 如果你的端點回傳錯誤狀態碼,webhook 可能會重試
  • 快速回應 – 盡快回傳 2xx 狀態碼
  • 使用 HTTPS – 在正式環境務必為 webhook 端點使用 HTTPS URL
  • 儲存原始內容 – 儲存原始 webhook 載荷,用於除錯與後續驗證
I