The ultimate Webhook infrastructure for your SaaS
Ingest, route, sign, and retry webhooks securely for thousands of tenants. Forget about managing chaotic queues and failing retries.
$ curl -X POST https://api.souris.io/v1/events \
-H "x-api-key: hk_live_acme8877bc" \
-d '{"eventType": "payment.succeeded", ...}'
✓ Event ingested successfully
→ Message enqueued: msg_90a3ffb1
→ Status: queued (Delivery in progress)
Designed for Critical Workloads
All the power of an enterprise webhook engine ready to be integrated in minutes.
Native Multi-Tenant
Isolate configurations, API keys, and queues per tenant. Each client has their own space and custom policies without mixing data.
Intelligent Retries
Configure exponential backoff and custom jitter. If your client's server goes down, Souris retries status-aware in a distributed manner.
HMAC-SHA256 Signatures
Secure delivery by signing each webhook with a unique secret key. Your subscribers can verify requests come from you infallibly.
Inbound Redirection
Ingest webhooks from external services and redirect them securely to your internal systems, normalizing the event type.
Monitoring & Logs
Access the attempt history of each message, including response times, status codes, and full responses from the remote server.
Scheduled Delivery
Send an event now to be delivered exactly in 3 hours, 2 days, or any specific future time using scheduledAt.
Live Webhook Simulator
Experience the webhook lifecycle, including failures, HMAC signatures, and automated retries.
Easy to Integrate
Send events to Souris with a simple REST API and verify HMAC signatures in your microservices.
curl -X POST https://api.souris.io/v1/events \
-H "Content-Type: application/json" \
-H "x-api-key: hk_live_acme8877bc" \
-d '{
"integrationId": "int_external_billing",
"eventType": "payment.succeeded",
"payload": {
"id": "pay_9921",
"amount": 4900,
"currency": "usd",
"customerId": "cus_99ab"
}
}'
const crypto = require('crypto');
// Express webhook handler: HMAC-SHA256 Signature Verification
app.post('/webhook-receiver', (req, res) => {
const signatureHeader = req.headers['x-souris-signature']; // 'sha256=...'
const secret = 'external-secret-key';
const hash = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(req.body))
.digest('hex');
if (signatureHeader !== `sha256=${hash}`) {
return res.status(401).send('Invalid Signature');
}
// Process webhook safely...
res.status(200).send('Webhook Processed');
});
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def verify_webhook():
signature = request.headers.get('x-souris-signature')
secret = b"external-secret-key"
computed = hmac.new(secret, request.data, hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, f"sha256={computed}"):
return "Unauthorized", 401
# Event verified and safe
return jsonify({"status": "success"}), 200
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"net/http"
)
func WebhookHandler(w http.ResponseWriter, r *http.Request) {
sig := r.Header.Get("x-souris-signature")
secret := []byte("external-secret-key")
mac := hmac.New(sha256.New, secret)
// Write body to hash and calculate sum
expectedMAC := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(sig), []byte("sha256="+expectedMAC)) {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusOK)
}
Flexible Plans
From indie developers to large-scale enterprises.
Perfect for prototyping and local testing.
- 1 Tenant
- Up to 10,000 webhooks/month
- 3 maximum retries
- Basic backoff delay
For growing companies with isolation needs.
- Up to 100 isolated Tenants
- 1,000,000 webhooks/month
- Configurable retries + Jitter
- HMAC signatures and detailed logs
- Webhook Inbound Redirection
For critical high loads and guaranteed SLAs.
- Unlimited Tenants & Integrations
- Unlimited webhook volume
- Advanced Backoff configuration
- Dedicated Technical Support
Frequently Asked Questions
Have questions about Souris? We answer the most common inquiries.
What is Inbound webhook redirection?
It consists of receiving webhooks from external third-party services in a public URL provided by Souris, which validates and normalizes the event type before securely routing it to your tenant backend.
How do Exponential Backoff and Jitter work?
Exponential backoff multiplies the wait time after each failed attempt (e.g. 500ms, 1000ms, 2000ms). Adding Jitter (random noise) prevents multiple retries from triggering at the same time and causing a stampede effect on the receiving server.
Can I configure retry limits per customer?
Yes, each tenant integration can override the global default configuration by defining its own values for maxRetries, backoffType, and backoffDelay.
How does Souris secure event delivery?
We generate HMAC-SHA256 signatures in the x-souris-signature header using an integration-specific shared secret. This allows the receiver to decode and validate that the data was not tampered with in transit.