Webhooks

Webhook Integration

Receive real-time notifications when scans complete or vulnerabilities are found.

How Webhooks Work

  1. 1
    Submit a scan with a webhook URL - Include your endpoint in the API request
  2. 2
    MCPSafe processes the scan - Analysis runs in the background
  3. 3
    Webhook is triggered - POST request sent to your URL with results

Submitting a Scan with Webhook

API Request

Include the webhook parameter when submitting a scan

cURL
curl -X POST https://api.mcpsafe.org/api/v1/scans/url \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://github.com/owner/repo",
    "webhook": "https://your-server.com/webhook/mcpsafe"
  }'

Webhook Events

scan.completed

Fired when a scan finishes successfully

scanId
url
results
reportUrl

scan.failed

Fired when a scan encounters an error

scanId
url
error
errorCode

vulnerability.found

Fired for each critical/high vulnerability (Pro+)

scanId
vulnerability
severity

Payload Example

scan.completed Event

Example payload sent to your webhook endpoint

POST payload
{
  "event": "scan.completed",
  "timestamp": "2024-01-15T10:30:45Z",
  "data": {
    "scanId": "scan_abc123xyz",
    "url": "https://github.com/owner/repo",
    "status": "completed",
    "results": {
      "securityScore": 72,
      "grade": "B",
      "vulnerabilities": {
        "critical": 0,
        "high": 1,
        "medium": 2,
        "low": 3,
        "info": 5,
        "total": 11
      }
    },
    "reportUrl": "https://mcpsafe.org/scan/scan_abc123xyz"
  }
}

Signature Verification

Verifying Webhook Signatures

Always verify the X-MCPSafe-Signature header to ensure webhooks are authentic

Node.js / Express
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expectedSignature}`)
  );
}

// Express.js example
app.post('/webhook/mcpsafe', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-mcpsafe-signature'];
  const payload = req.body.toString();

  if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(payload);
  console.log('Received webhook:', event.event);

  // Handle the event
  switch (event.event) {
    case 'scan.completed':
      handleScanCompleted(event.data);
      break;
    case 'scan.failed':
      handleScanFailed(event.data);
      break;
  }

  res.status(200).json({ received: true });
});

Security Warning

Always verify webhook signatures before processing. Never trust the payload without verification.

Best Practices

Respond Quickly

Return 2xx within 30 seconds or we'll retry

Use HTTPS

Webhook URLs must use HTTPS for security

Handle Duplicates

Same event may be sent multiple times on retry

Process Async

Queue events for background processing

Retry Policy

If your endpoint doesn't respond with a 2xx status code, we'll retry:

  • 1
    Immediately after failure
  • 2
    1 minute later
  • 3
    5 minutes later
  • 4
    30 minutes later (final attempt)