Skip to main content

Best Practices

1. Always verify signatures

Never process unverified webhook events:

// ✅ Always verify first
app.post('/webhook', (req, res) => {
const result = sdk.getEventFromRequest(req, WEBHOOK_SECRET);

if (!result.isValid) {
return res.status(400).json({ error: result.error });
}

processEvent(result.payload);
});

2. Handle retries gracefully

Make your webhook endpoint idempotent:

const processedEvents = new Set();

app.post('/webhook', (req, res) => {
const result = sdk.getEventFromRequest(req, WEBHOOK_SECRET);

if (!result.isValid) {
return res.status(400).json({ error: result.error });
}

const payload = result.payload;

// Check if already processed
if (processedEvents.has(payload.id)) {
console.log('Event already processed:', payload.id);
return res.json({ received: true });
}

// Process the event
processEvent(payload);

// Mark as processed
processedEvents.add(payload.id);

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

3. Respond quickly

Return HTTP 200 as soon as possible to avoid timeouts:

app.post('/webhook', (req, res) => {
const result = sdk.getEventFromRequest(req, WEBHOOK_SECRET);

if (!result.isValid) {
return res.status(400).json({ error: result.error });
}

// Respond immediately
res.json({ received: true });

// Process asynchronously
setImmediate(() => {
processEvent(result.payload);
});
});

4. Log events

Keep logs for debugging and monitoring:

app.post('/webhook', (req, res) => {
const result = sdk.getEventFromRequest(req, WEBHOOK_SECRET);

if (!result.isValid) {
console.error('Webhook validation failed:', result.error);
return res.status(400).json({ error: result.error });
}

const payload = result.payload;
console.log('Event received:', payload.id, payload.event.name);

processEvent(payload);
res.json({ received: true });
});

5. Secure your secret

Store webhook secrets securely:

// ✅ Use environment variables
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
if (!WEBHOOK_SECRET) {
throw new Error('WEBHOOK_SECRET environment variable is required');
}

Troubleshooting

Common Issues

Signature verification fails

  • Check that you're using the correct webhook secret
  • Ensure the payload hasn't been modified
  • Verify the signature header is being read correctly

Events not being received

  • Check that your webhook URL is accessible from the internet
  • Verify your webhook is enabled in MOUNTAIN
  • Check your server logs for errors

Duplicate events

  • Implement idempotency using event IDs
  • Check for retry logic in your error handling

Next Steps