Webhooks

webhook URL로 에이전트를 만들면 Cursor가 상태 변경을 알려주는 HTTP POST 요청을 보내. 현재는 statusChange 이벤트만 지원하고, 에이전트가 ERROR 또는 FINISHED 상태가 될 때만 보내.

Webhook 검증

Webhook 요청이 실제로 Cursor에서 온 건지 확인하려면, 각 요청에 포함된 서명을 검증해:

Headers

각 webhook 요청에는 다음 헤더가 포함돼:
  • X-Webhook-Signaturesha256=<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
서명을 계산할 때는 항상 파싱 전에 원본 요청 본문(raw body)을 사용해.

페이로드 형식

웹훅 페이로드는 아래 구조의 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": "설치 안내가 포함된 README.md 추가"
}
일부 필드는 선택적이며, 사용 가능한 경우에만 포함돼.

모범 사례

  • 서명 검증 – 요청이 Cursor에서 온 게 맞는지 확인하려면 항상 웹훅 서명을 검증해
  • 재시도 처리 – 엔드포인트가 오류 상태 코드를 반환하면 웹훅이 재시도될 수 있어
  • 빠르게 응답 – 가능한 한 빨리 2xx 상태 코드를 반환해
  • HTTPS 사용 – 프로덕션에서는 웹훅 엔드포인트에 항상 HTTPS URL을 사용해
  • 원시 페이로드 저장 – 디버깅과 추후 검증을 위해 웹훅 원시 페이로드를 저장해