SMS Verification Webhook Security: 7 Best Practices (2026)
How to secure your SMS verification webhooks against replay attacks, man-in-the-middle, and unauthorized access. With production code examples.
Why webhook security matters
Webhooks are the most common attack surface for SMS APIs. A compromised webhook lets attackers:
- Trigger SMS rentals on your account (costing money)
- Intercept verification codes (breaking security)
- Cause downtime by spamming your endpoint
7 security practices
1. Verify HMAC signatures
Every webhook should include a cryptographic signature. RCVSMS uses HMAC-SHA256.
2. Use HTTPS only
Never accept webhooks over HTTP. Most webhook providers (Stripe, Twilio, etc.) reject HTTP.
3. Implement timestamp validation
Reject events older than 5 minutes to prevent replay attacks.
4. Use unique, random webhook secrets
Don't reuse passwords or other API keys.
5. Whitelist source IPs
RCVSMS publishes its webhook IP ranges.
6. Idempotency keys
Use the event ID to prevent double-processing.
7. Rate limit your endpoint
Even with signature verification, protect against DoS.
Code example (Node.js)
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhooks/sms', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-rcvsms-signature'];
const timestamp = req.headers['x-rcvsms-timestamp'];
const body = req.body;
// Verify timestamp (5 minute window)
const ageSeconds = (Date.now() / 1000) - parseInt(timestamp);
if (ageSeconds > 300) {
return res.status(401).send('Stale timestamp');
}
// Verify HMAC
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(`${timestamp}.${body.toString()}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(body);
handleEvent(event);
res.status(200).send('OK');
});
Testing
Test your webhook handler with the RCVSMS CLI:
rcvsms webhook:test --url https://your-app.com/webhooks/sms
This sends a signed test event you can use to validate your implementation.
Ready to rent your first number?
Get started in under 2 minutes. No subscription required.
Get started for $0.24