# Webhooks - Verification

Verify webhook authenticity and handle URL validation.

## Overview

Zoom provides two verification mechanisms:
1. **URL Validation** - Verify your endpoint during setup
2. **Request Signature** - Verify each webhook request

## URL Validation

When you configure a webhook endpoint, Zoom sends a validation request:

```json
{
  "event": "endpoint.url_validation",
  "payload": {
    "plainToken": "random_token_string"
  }
}
```

### Response Required

Hash the token with your webhook secret and respond:

```javascript
const crypto = require('crypto');

app.post('/webhook', (req, res) => {
  const { event, payload } = req.body;
  
  if (event === 'endpoint.url_validation') {
    const hashForValidation = crypto
      .createHmac('sha256', WEBHOOK_SECRET_TOKEN)
      .update(payload.plainToken)
      .digest('hex');
    
    return res.json({
      plainToken: payload.plainToken,
      encryptedToken: hashForValidation
    });
  }
  
  // Handle other events...
  res.status(200).send();
});
```

## Request Signature Verification

Verify each webhook request is from Zoom:

### Headers

| Header | Description |
|--------|-------------|
| `x-zm-signature` | Request signature |
| `x-zm-request-timestamp` | Request timestamp |

### Verification Code

```javascript
const crypto = require('crypto');

function verifyWebhook(req) {
  const signature = req.headers['x-zm-signature'];
  const timestamp = req.headers['x-zm-request-timestamp'];
  // Prefer raw body bytes captured by your framework to avoid JSON re-serialization mismatches.
  const body = req.rawBody ? req.rawBody.toString('utf8') : JSON.stringify(req.body);
  
  const message = `v0:${timestamp}:${body}`;
  const hash = crypto
    .createHmac('sha256', WEBHOOK_SECRET_TOKEN)
    .update(message)
    .digest('hex');
  
  const expectedSignature = `v0=${hash}`;
  
  return signature === expectedSignature;
}
```

## Security Best Practices

1. Always verify signatures
2. Check timestamp to prevent replay attacks
3. Use HTTPS endpoints only
4. Keep webhook secret secure

## Resources

- **Webhook verification**: https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events
