# Webhooks Reference
Receive instant updates on verification events directly on your backend.
---
Instead of exhausting network and client resources with active HTTP polling, you can define a **Webhook URL** inside your project settings in the dashboard.
As soon as a user's phone number is verified, the ReOTP server sends a direct POST request containing the verification payload to your backend.
### Secure Webhooks (Webhook Signature)
If you configure a webhook secret in the settings, we will include an x-webhook-signature header containing an HMAC SHA256 signature of the payload. You should compute the HMAC of the raw request body using your secret and compare it to this header to verify authenticity.
## Code Examples
### Payload
```json
{
"event": "verification.success",
"phoneNumber": "+966500000000",
"actualPhoneNumber": "+966500000000",
"requestId": "cmrjpk97j0000okc514kfdkll",
"projectId": "cmrjpk97j00...",
"method": "WHATSAPP",
"timestamp": "2026-07-17T12:00:00.000Z"
}
```
### Node.js Express
```json
const express = require('express');
const crypto = require('crypto');
const app = express();
// Use express.raw or express.json to get the payload string
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString();
}
}));
app.post('/webhook/reotp', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const secret = 'YOUR_WEBHOOK_SECRET';
// Calculate expected signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(req.rawBody)
.digest('hex');
// Verify webhook sender authenticity
if (signature !== expectedSignature) {
return res.status(401).send('Unauthorized');
}
const { event, phoneNumber, requestId } = req.body;
if (event === 'verification.success') {
console.log(`Successfully verified phone ${phoneNumber}!`);
// Mark user as verified in your local database
}
res.status(200).send('Received');
});
```