Webhook Debugging
Monitor, test, and troubleshoot webhook deliveries from the Safravo dashboard.
Accessing the monitoring panel
Open the endpoint panel
Go to Settings → Webhooks and click the endpoint you want to inspect.
Read the delivery logs
The Logs tab shows the 50 most recent delivery attempts, sorted newest-first.
| Field | Description |
|---|---|
| Event type | e.g. message.created |
| Status | HTTP response code returned by your server |
| Timestamp | When the delivery was attempted |
| Latency | How long your server took to respond |
Logs expire automatically after 30 days.
Troubleshooting common errors
Circuit breaker (auto-disable)
Safravo uses an automatic circuit breaker to prevent overwhelming failing endpoints.
| Status | Condition |
|---|---|
active | Receiving events normally |
failing | 5+ consecutive failures — investigate immediately |
disabled | 25 consecutive failures — auto-disabled, manual re-enable required |
The failure counter resets to zero on any successful delivery. When an endpoint is auto-disabled, Safravo sends an email notification to the workspace owner.
Re-enabling a disabled endpoint
Fix the issue on your server
Resolve the underlying problem — check your application logs, verify your signature verification code, and confirm your server is publicly reachable.
Re-enable in the dashboard
Go to Settings → Webhooks, find the disabled endpoint, and click Re-enable.
Wait for the cooldown
The first delivery attempt is delayed by 5 minutes as a cooldown. After that, events resume normally.
Delivery retries
Failed deliveries are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 (initial) | Immediate |
| 2 | 5 seconds |
| 3 | 30 seconds |
| 4 | 2 minutes |
| 5 | 10 minutes |
| 6–10 | 1 hour each |
After 10 failed attempts, that specific event delivery is marked permanently failed.
Testing locally
Use ngrok or Cloudflare Tunnel to expose your local server:
# ngrok
ngrok http 3000
# Cloudflare Tunnel (stable URL, free)
cloudflared tunnel --url http://localhost:3000Register the tunnel URL as your webhook endpoint in Settings → Webhooks. Update it whenever the tunnel restarts — the free tier of ngrok generates a new URL on every restart.
Cloudflare Tunnel is free and provides a stable URL that persists across restarts, making it a better choice than ngrok free tier for local development.
Deduplication
Safravo may deliver the same event more than once during retries. Use the X-Safravo-Delivery header as an idempotency key:
const deliveryId = req.headers['x-safravo-delivery'];
const alreadyProcessed = await redis.get(`webhook:${deliveryId}`);
if (alreadyProcessed) {
return res.status(200).json({ received: true }); // idempotent
}
// ... process event ...
await redis.setex(`webhook:${deliveryId}`, 86400, '1'); // TTL: 24 hours